- FROM 指定基础镜像
对于这条指令的理解大概可以这样理解,比如,我们搭建mysql服务时会说基于centos搭建mysql服务,这个基于的centos实际上就是dockerfile中的基础镜像。
指令基本格式:
1 | FROM scratch |
1 | FROM centos |
- RUN 执行命令行命令
有两种格式- shell格式,就像在命令行执行命令一样
1 | FROM centos |
- exec 格式
1 | RUN ["可执行文件", "参数1", "参数2"],这更像是函数调用中的格式 |
应该尽可能的把连续的命令使用&&符号连到一起,这样可以避免制作的镜像过大,原因是dockerfile中每条指令都会建立一层,如果多条指令不用&&串联,那么有几条指令就会建立几层,这样就会使镜像显得十分臃肿!
- COPY 复制文件到容器
1 | COPY srcdir destdir |
支持通配符操作
1 | COPY *.txt /tmp/ |
COPY会保留文件的属性,需要更改属性就要用到ADD
- ADD 更高级的复制文件
ADD比COPY多了一些功能,比如源文件可以是url地址,还有如果源文件是以gzip
bzip2 xz压缩的tar文件,他会自动解压到目标文件,其格式为
1 | ADD http://nginx.org/download/nginx-1.13.5.tar.gz /tmp/ |
1 | ADD nginx-1.13.5.tar.gz /usr/local/ |
但是 ADD 从url下载的文件默认权限是600,如果想要更改权限还是要是用RUN去更改,还有自动解压并不是我们每次都希望的事,所以我们要分清什么时候用ADD 什么时候用COPY —-仅当需要自动解压压缩文件到目标目录时,我们用ADD ,需要下载url时用RUN +crul/wget 需要复制文件到容器内用COPY
- CMD容器启动进程命令 和RUN一样也有两种格式
CMD <命令>
CMD [”可执行文件”,”参数1”,“”参数2”]
1.不建议使用CMD <命令>这种格式,即使使用实际执行时也是包装为CMD [”可执行文件”,”参数1”,“”参数2”]这种格式的,比如CMD ls /tmp/ ===>CMD [“sh”,”-c”,”ls /tmp/“]
2.关于容器执行命令前后台的问题,容器是为了主进程而存在的,主进程退出,容器也就失去了存在的意义,所以,你在创建容器是执行service nginx start 发现创建完容器自动退出,因为service nginx start是希望nginx以守护进程而运行,换而言之,这里的主进程是service nginx start 而启动脚本中的nginx -g是辅助进程,容器并不关心辅助进程,主进程service nginx start 执行完退出,容器也就随之退出
- ENTRYPOINT 和CMD 一样指定容器内启动程序的参数,格式也是有两种
ENTRYPOINT <命令>
ENTRYPOINT [”可执行文件”,”参数1”,“”参数2”]
ENTRYPOINT的使用场景,一般是搭配CMD使用,及将CMD作为ENTRYPOINT执行命令的参数来使用!
例如下面是一个构建查询本机外网ip的dockerfile:
1 | FROM hub.c.163.com/public/centos:6.7-tools |
docker build 构建:
1 | ➜ localhost_wwip git:(master) ✗ docker build -t getip:v1 . |
运行:
1 | ➜ localhost_wwip git:(master) ✗ docker run getip:v1 |
但是如果我想获取curl头部信息怎么办?
- 修改dockerfile,CMD 加入-i参数
1 | FROM hub.c.163.com/public/centos:6.7-tools |
- 重新构建后,执行docker命令
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22➜ localhost_wwip git:(master) ✗ docker build -t getip:v1.1 .
Sending build context to Docker daemon 2.048kB
Step 1/3 : FROM hub.c.163.com/public/centos:6.7-tools
---> b2ab0ed558bb
Step 2/3 : RUN yum install curl -y && rm -fr /var/lib/yum/*
---> Using cache
---> 891dda232e64
Step 3/3 : CMD curl -s -i http://ip.cn
---> Running in bf0d517417f0
---> 01824f12a875
Removing intermediate container bf0d517417f0
Successfully built 01824f12a875
Successfully tagged getip:v1.1
➜ localhost_wwip git:(master) ✗ docker run getip:v1.1
HTTP/1.1 200 OK
Server: nginx/1.11.9
Date: Wed, 13 Sep 2017 05:11:05 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
当前 IP:180.173.192.249 来自:上海市 电信
但是我们不想每次都输出头部信息,可能有那么一两次想要去查看,那怎么办?有人说,加docker run 时加-i,这显然就没有明白CMD这个命令的用法
1 | ➜ localhost_wwip git:(master) ✗ docker run getip:v1 -i |
很显然报错了,因为-i 会替换 curl -s http://ip.cn
那怎么办?这时ENTRYPOINT就发挥作用了,我们更改下dockerfile
1 | FROM hub.c.163.com/public/centos:6.7-tools |
1 | ➜ localhost_wwip git:(master) ✗ docker build -t getip:v1.2 . |
这样我们看到就可以在docker run 后添加参数来满足我们的不同需求了
- ENV 设置环境变量
1 | FROM hub.c.163.com/public/centos:6.7-tools |
支持变量的指令有:
ADD、COPY、ENV、EXPOSE、LABEL、USER、WORKDIR、VOLUME、STOPSIGNAL、ONBUILD
- ARG 构建参数
和ENV一样,也是用于声明变量,但是只在构建镜像时生效,启动容器时不生效。ARG只是指定某个参数的默认值,可以在docker build 构建镜像时使用–build-arg覆盖dockerfile中定义的默认值
- VOLUME 指定匿名券
1 | VOLUME /data |
容器运行时需要写入数据时应该写到容器外而不是容器内,这样可以防止数据丢失,也可以在docker容器迁移时不至于过大造成的不便,利用VOLUME 指定匿名券,这样容器发生写的操作时就会写到默认的匿名券中,也可以在docker run 构建容器时指定挂载名 -v 挂载名:/mydata
1 | FROM hub.c.163.com/public/centos:6.7-tools |
1 | nginx git:(master) ✗ docker build -t nginx:v0.2 . |
可以看到容器中mydata的挂载
- EXPOSE 声明端口
1 | EXPOSE PORT1 PORT2 ... |
只是简单的声明,并不会在容器启动时自动映射声明的端口,声明端口-p 宿主端口:容器端口 -P 容器端口(随机分配宿主端口)
- WORKDIR 指定工作目录 如果不存在测创建
dockerfile中不能用RUN cd dir来切换工作目录 因为dockerfile的每一层都是单独存在,其工作目录如果workdir指定,那其后的每一层的工作目录均为workdir指定的目录,如果不指定则为默认。
- USER 指定当前用户
USER和WORKDIR的作用一样,改变环境状态并影响以后的层
1 | USER nginx |
- 本文作者: ChuLinx
- 本文链接: http://yoursite.com/2019/11/30/docker之dockerfile基础详解/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!