DockerFile常用命令
COPY 复制文件
COPY [--chown=<user>:<group>] <源路径>... <目标路径>
COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]
COPY 指令将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置。
COPY package.json /usr/src/app/ 这个是把【上下文】路径下的package.json文件复制到【容器】的/usr/src/app/下
源路径可以是多个,并且支持通配。
COPY hom* /mydir/ COPY hom?.txt /mydir/
<目标路径> 可以是容器内的【绝对路径】,也可以是相对于【工作目录】的相对路径(工作目录可以用 WORKDIR 指令来指定)。目标路径不需要事先创建,如果目录不存在会在复制文件前先行创建缺失目录。
PS:使用 COPY 指令,源文件的各种元数据都会保留 可以加上--chown=<user>:<group> 来确定用户和用户组。
ADD高级复制命令
ADD 指令和 COPY 的格式和性质基本一致。但是在 COPY 基础上增加了一些功能。
1.<源路径>可以是url,下载后权限600.
2.支持tar压缩包,会自动解压。
CMD 容器启动命令
CMD 指令的格式和 RUN 相似,也是两种格式:
shell 格式: CMD <命令>
exec 格式: CMD ["可执行文件", "参数1", "参数2"...]
参数列表格式: CMD ["参数1", "参数2"...] 。在指定了 ENTRYPOINT 指令后,用 CMD 指定具体的参数。
CMD 指令就是用于指定默认的容器主进程的启动命令的。
比如直接执行 docker run -it ubuntu 其实是启了bash,因为这个镜像默认的CMD是/bin/bash,当然也可以再启动的时候指定运行程序,比如这样:
docker run -it ubuntu cat /etc/os-release,这会直接输出版本信息的
书中是建议使用exec格式,这类格式在解析时会被解析为JSON数组(因此一定用双引号不要用单引号)。
如果使用shell格式的话,实际的命令会被包装为 sh -c 的参数形式进行执行。比如:
CMD echo $HOME 在实际执行中,会将其变更为:CMD["sh", "-c", "echo $HOME"],也因为这个特点,才可以使用环境变量,因为shell会进行解析环境变量。
容器中应用在前台执行和后台执行的问题
Docker不是虚拟机,容器中的应用都应该在前台执行,而不像是虚拟机、物理机那样,用systemd去启动后台服务,容器内没有后台服务的概念。
比如 执行 CMD service nginx start 这个应该是想要后台启动nginx当服务用,但是真这么执行的时候,容器会立刻退出的。对于容器而言,其启动程序就是容器应用进程,容器就是为了住进程而存在的,主进程退出,容器就是去了存在的意义,从而退出,其他辅助进程不是它需要关心的东西。使用 service nginx start 是希望upstart来以后台守护进程形式起的弄nginx服务。其实这个会被解析成
CMD["sh","-c","service nginx start"] ,因此主进程实际上是sh。执行完service nginx start后,sh就没事了,也就是主进程没事了,主进程没事了的话,容器就没事了。所以就退出了。
所以可以直接,前台运行nginx CMD["nginx","-g","daemon off;"]
ENTRYPOINT 入口点
ENTRYPOINT格式也是分为exec和shell。
ENTRYPOINT的目的和CMD一样,都是指定容器启动及其参数,但是他有单独的用处。
如果指定了ENTRYPOINT的话,CMD的内容将会变成参数:<ENTRYPOINT> "<CMD>"
看下实际用途:
创建一个镜像,功能是获取本地ip,Dockerfile里这么写
FROM ubuntu:18.04
RUN apt-get update \
&& apt-get install -y curl \
&& rm -rf /var/lib/apt/lists/*
CMD ["curl","-s","https://ip.cn"]
然后做一个镜像 docker build -t myip . [记得上面创建的Dockerfile放在当前路径下]
启动下看看 docker run myip
我的输出结果是 {"ip": "221.217.52.233", "country": "北京市", "city": "联通"}
OK目前看没啥问题,默认执行的是CMD里面设置好的东西,但是如果现在想继续加参数会咋样,比如说加上 -i参数
我们其实想实现这样的效果 docker run myip curl -s https://ip.cn -i
然后尝试的这么执行的 docker run myip -i
得到的结果是这个:docker: Error response from daemon: OCI runtime create failed: container_linux.go:346: starting container process caused "exec: \"-i\": executable file not found in $PATH": unknown.
和想象的不一样,原因是:跟在镜像名后面的是 command ,运行时会替换 CMD 的默认值。因此这里的 -i 替换了原来的 CMD ,而不是添加在原来的 curl -s
所以引入了ENTRYPOINT
FROM ubuntu:18.04
RUN apt-get update \
&& apt-get install -y curl \
&& rm -rf /var/lib/apt/lists/*
ENTRYPOINT ["curl","-s","https://ip.cn"]
创建新的镜像 docker build -t myip2 .
执行docker run myip2 -i
结果是:
HTTP/2 200
date: Thu, 28 Nov 2019 15:23:01 GMT
content-type: application/json; charset=UTF-8
set-cookie: __cfduid=d2f01f73f37cc1d1bbf92e970d887583a1574954581; expires=Sat, 28-Dec-19 15:23:01 GMT; path=/; domain=.ip.cn; HttpOnly
cf-cache-status: DYNAMIC
expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
server: cloudflare
cf-ray: 53cd57349d3ae79c-LAX
{"ip": "221.217.52.233", "country": "北京市", "city": "联通"}
所以说成功了。
ENTRYPOINT还有一个应用场景,就是运行前的准备工作:可以写一个脚本,然后放入 ENTRYPOINT 中去执行,而这个脚本会将接到的参数(也就是 <CMD> )作为命令,在脚本最后执行。比如官方镜像 redis 中就是这么做的:
FROM alpine:3.4
...
RUN addgroup -S redis && adduser -S -G redis redis
...
ENTRYPOINT ["docker-entrypoint.sh"]
EXPOSE 6379
CMD [ "redis-server" ]
其中为了 redis 服务创建了 redis 用户,并在最后指定了 ENTRYPOINT为 docker-entrypoint.sh 脚本
#!/bin/sh
...
# allow the container to be started with `--user`
if [ "$1" = 'redis-server' -a "$(id -u)" = '0' ]; then
chown -R redis .
exec su-exec redis "$0" "$@"
fi
exec "$@"
该脚本的内容就是根据 CMD 的内容来判断,如果是 redis-server 的话,则切换到 redis 用户身份启动服务器,否则依旧使用 root 身份执行
ENV 设置环境变量
ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...
无论是后面的其它指令,如 RUN ,还是运行时的应用,都可以直接使用这里定义的环境变量。
例如可以这么写[注意换行符和 空格字符串的处理]
ENV VERSION=1.0 DEBUG=on \
NAME="Happy Feet"
到时候引用的时候就可以在下面直接这样
XXXXX " xxxx$VERSION xxxxxx"
ARG 构建参数
格式: ARG <参数名>[=<默认值>]
构建参数和 ENV 的效果一样,都是设置环境变量。所不同的是, ARG 所设置的构建环境的环境变量,在将来容器运行时是不会存在这些环境变量的。但是不要因此就使用 ARG 保存密码之类的信息,因为 docker history 还是可以看到所有值的。Dockerfile 中的 ARG 指令是定义参数名称,以及定义其默认值。该默认值可以在构建命令 docker build 中用 --build-arg <参数名>=<值> 来覆盖。
VOLUME 定义匿名卷
格式为:
VOLUME ["<路径1>", "<路径2>"...]
VOLUME <路径>
容器运行时应该尽量保持容器存储层不发生写操作,对于数据库类需要保存动态数据的应用,其数据库文件应该保存于卷(volume)中,在 Dockerfile 中,可以事先指定某些目录挂载为匿名卷,这样在运行时如果用户不指定挂载,其应用也可以正常运行,不会向容器存储层写入大量数据。
VOLUME /data
这里的 /data 目录就会在运行时自动挂载为匿名卷,任何向 /data 中写入的信息都不会记录进容器存储层,从而保证了容器存储层的无状态化。
也可以执行 docker run -d -v mydata:/data xxxx
在这行命令中,就使用了 mydata 这个命名卷挂载到了 /data 这个位置,替代了 Dockerfile 中定义的匿名卷的挂载配置。
ps:如果是mac的话注意一个问题,就是mac的docker不是直接跑在本地的,是跑在本地虚拟机里的,所以说如果你是在设置完卷或者是查找完卷之后没有在本地找到路径是对的。需要登陆到虚拟机里面去,在虚拟机里面找对应的路径 进入本地虚拟机输入 screen ~/Library/Containers/com.docker.docker/Data/vms/0/tty
然后回车就行了,还有就是遇到一个问题,不要强行关闭到shell窗口,这样再打开shell窗口然后重新登陆到本地虚拟机会又问题,登不进去。
EXPOSE 声明端口
格式为 EXPOSE <端口1> [<端口2>...]
EXPOSE 指令是声明运行时容器提供服务端口,这只是一个声明,在运行时并不会因为这个声明应用就会开启这个端口的服务。在 Dockerfile 中写入这样的声明有两个好处,一个是帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射;另一个用处则是在运行时使用随机端口映射时,也就是 docker run -P时,会自动随机映射 EXPOSE 的端口。
要将 EXPOSE 和在运行时使用 -p <宿主端口>:<容器端口> 区分开来。 -p ,是映射宿主端口和容器端口,换句话说,就是将容器的对应端口服务公开给外界访问,而 EXPOSE 仅仅是声明容器打算使用什么端口而已,并不会自动在宿主进行端口映射。
WORKDIR 指定工作目录
格式为 WORKDIR <工作目录路径> 。
使用 WORKDIR 指令可以来指定工作目录(或者称为当前目录),以后各层的当前目录就被改为指定的目录,如该目录不存在, WORKDIR 会帮你建立目录。
USER 指定当前用户
格式: USER <用户名>[:<用户组>]
例子:
RUN groupadd -r redis && useradd -r -g redis redis
USER redis
RUN [ "redis-server" ]
HEALTHCHECK 健康检查
格式:
HEALTHCHECK [选项] CMD <命令> :设置检查容器健康状况的命令
HEALTHCHECK NO
在没有 HEALTHCHECK 指令前,Docker 引擎只可以通过容器内主进程是否退出来判断容器是否状态异常。很多情况下这没问题,但是如果程序进入死锁状态,或者死循环状态,应用进程并不退出,但是该容器已经无法提供服务了。
当在一个镜像指定了 HEALTHCHECK 指令后,用其启动容器,初始状态会为starting ,在 HEALTHCHECK 指令检查成功后变为 healthy ,如果连续一定次数失败,则会变为 unhealthy 。
HEALTHCHECK 支持下列选项:
--interval=<间隔> :两次健康检查的间隔,默认为 30 秒;
--timeout=<时长> :健康检查命令运行超时时间,如果超过这个时间,本次健康检查就被视为失败,默认 30 秒;
--retries=<次数> :当连续失败指定次数后,则将容器状态视为unhealthy ,默认 3 次。和 CMD , ENTRYPOINT 一样, HEALTHCHECK 只可以出现一次,如果写了多个,只有最后一个生效。
例子,web服务的健康体检
FROM nginx
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
HEALTHCHECK --interval=5s --timeout=3s \
CMD curl -fs http://localhost/ || exit 1
ONBUILD 最为基础镜像的时候在执行
格式: ONBUILD <其它指令> 。
ONBUILD 是一个特殊的指令,它后面跟的是其它指令,比如 RUN , COPY 等,而这些指令,在当前镜像构建时并不会被执行。只有当以当前镜像为基础镜像,去构建下一级镜像的时候才会被执行。
例子:
FROM node:slim
RUN mkdir /app
WORKDIR /app
ONBUILD COPY ./package.json /app
ONBUILD RUN [ "npm", "install" ]
ONBUILD COPY . /app/
CMD [ "npm", "start" ]
ONBUILD前缀的都是这次不执行,下次执行。
DockerFile常用命令的更多相关文章
- 016、Dockerfile 常用命令(2019-01-07 周一)
参考https://www.cnblogs.com/CloudMan6/p/6864000.html Dokcerfile常见命令 FROM 指定base镜像 MAINTAINER ...
- Dockerfile指令及docker的常用命令
DockerfileFROM: FROM <image> FROM <image>:<tag> MAINTAINER: MAINTAINER <name> ...
- Docker 常用命令和Dockerfile
Docker 简介 官方的解释为:Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows 机器上,也可以实现 ...
- Dockerfile自动制作Docker镜像(二)—— 其它常用命令
Dockerfile自动制作Docker镜像(二)-- 其它常用命令 前言 a. 本文主要为 Docker的视频教程 笔记. b. 环境为 CentOS 7.0 云服务器 c. 上一篇:Dockerf ...
- docker常用命令、镜像命令、容器命令、数据卷,使用dockerFile创建镜像,dockefile的语法规则。
一.docker常用命令? 1. 常用帮助命令 1.1 docker的信息以及版本号 /* docker info 查看docker的信息 images2 docker本身就是一个镜像. docker ...
- Dockerfile 中对常用命令详解
说明 Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明. 在Dockerfile 中命令书写对先后顺序及表示其执行对顺序,在书写时需注意. 约定 命令不 ...
- Docker常用命令和Dockerfile语法
Linux安装Docker: sudo wget -qO- https://get.docker.com/ | sh 安装后只能用root管理,要给其他用户权限,使用命令: sudo usermod ...
- docker-image container 基本操作 -常用命令
基本概念: container 容器.可以把每个 container 看做是一个独立的主机. container 的创建通常有一个 image 作为其模板.类比成虚拟机的话可以理解为 image 就是 ...
- 关于Docker 常用命令
Docker 常用命令 分类列一下常用的CLI命令 仓库相关 search/ pull / push / login etc. 例:docker pull ubuntu 从仓库下载ubuntuimag ...
随机推荐
- java将一个list转换成一个String,中间用分隔符隔开
List sn=[123,1231,1231,231] sn.toString();//[123,1231,1231,231] sn.join(',').toString();//123,1231,1 ...
- 树莓派 3/4 安装 FreeBSD
已盼春来归 已盼春来归 今日去 愿为春来归 盼归春天来了 FreeBSD 的春天在哪里? 树莓派是什么,相信凡是关注了我们的人都不会不知道,但是介于非专业人员需要在此做简要介绍.我们的安卓手机,大部分 ...
- 2019 GDUT Rating Contest I : Problem G. Back and Forth
题面: G. Back and Forth Input file: standard input Output file: standard output Time limit: 1 second Mem ...
- 简单ping确定网络故障
1.ping localhost (127.0.0.1) 目的:确定TCP/IP有无问题 2.ping本机地址 用来检测网卡驱动有无问题 如何获取本机地址? win+r cmd 输入ipconfig/ ...
- Java 8 Stream API 详解
Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利.高效的聚合操作(aggregate operation),或者大批量数据操作 (b ...
- 解Bug之路-主从切换"未成功"?
解Bug之路-主从切换"未成功"? 前言 数据库主从切换是个非常有意思的话题.能够稳定的处理主从切换是保证业务连续性的必要条件.今天笔者就来讲讲主从切换过程中一个小小的问题. 故障 ...
- Java例题_20 前20项之和!
1 /*20 [程序 20 求前 20 项之和] 2 题目:有一分数序列:2/1,3/2,5/3,8/5,13/8,21/13...求出这个数列的前 20 项之和. 3 程序分析:请抓住分子与分母的变 ...
- 14、运行Django时浏览器中遇到Refused to display 'url' in a frame because it set 'X-Frame-Options' to 'deny'
问题:Refused to display 'url' in a frame because it set 'X-Frame-Options' to 'deny' 解决办法: 只需要在 Djagno ...
- 学习Typora来写博客
Typora学习 标题分级 知识详解 标题分级可使用快捷键Ctry+数字键(1.2.3.4.5.6.0) 例如Ctry+1为一级标题,Ctry+2为二级标题,以此类推,总共可分为六个级别的标题,Ctr ...
- Python基础(十四):while循环与break、continue关键字
前面我们已经学习了for循环,今天再带着大家讲述一下while循环.那么for循环和while循环,到底有什么区别呢? Python中for循环和while循环本质上是没有区别的,但是在实际应用上,针 ...