文章目录
- 1. 写在前面
- 2. 概念
- 3. 实际操作
- 3.1 FROM指令
- 3.2 RUN指令
- 3.3 构建镜像
- 4. 常用指令详解
- 4.1 COPY
- 4.2 CMD
- 4.3 ENV
- 4.4 ARG
- 4.5 EXPOSE
- 4.6 WORKDIR
- 5. 其他指令介绍
- 5.1 ENTRYPOINT
- 5.2 ADD
- 5.3 VOLUME
- 5.4 USER
- 5.5 HEALTHCHECK
- 5.6 ONBUILD
- 5.7 LABEL
1. 写在前面
本文主要针对后端开发人员,主要介绍如何编写我们需要的 Dockerfile,同时结合平时的使用经验,对Dockerfile中的命令进行详细的介绍。
2. 概念
Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。
一般构建流程如下:
编写Dockerfile
Dockerfile RUN...
Dockerfile FROM...
Dockerfile CMD...
docker build
3. 实际操作
下面使用 Dockerfile 定制镜像,以 python 工程为例,新建 Dockerfile 文件,添加如下内容:
FROM python:3.7
MAINTAINER xiaoi
# 开放端口
EXPOSE 5000
# 设置环境变量
ENV pypi https://pypi.douban.com/simple
ENV DIR /mnt/HttpServer
# 切换工作目录
COPY ./ ${DIR}
WORKDIR ${DIR}
RUN pip install --no-cache-dir -r requirements.txt flask uwsgi -i ${pypi}
CMD ["sh","app.sh"]
3.1 FROM指令
定制的镜像都是基于FROM
的镜像,这里的 python:3.7 就是定制需要的基础镜像,所有的操作都是基于 python:3.7。
3.2 RUN指令
用于执行后面跟着的命令行命令,有以下2种格式:
- shell 格式:
RUN ./app.sh 8080 greedy
- exec 格式:
RUN ["./app.py", "8080", "greedy"]
注意:Dockerfile 的指令每次执行都会在原来的基础上新建一层,过多的无意义层,会导致镜像过大。
下面我们来举个例子:
FROM centos
RUN yum install wget
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-6.2.5.tar.gz"
RUN tar -xvf redis.tar.gz
以上构建会创建 3 层镜像,为了简化为,改为以下内容:
FROM centos
RUN yum install wget \
&& wget -O redis.tar.gz "http://download.redis.io/releases/redis-6.2.5.tar.gz" \
&& tar -xvf redis.tar.gz
通过&&
连接执行命令,只创建了1层镜像。
3.3 构建镜像
构建命令命令如下:
$ docker build -t HttpServer:v1 .
命令最后的.
,表示会在 Dockerfile 文件存放的目录下执行构建操作。
顺便提一下,docker build
命令得知这个路径后,会将路径下的所有内容打包,由于 docker 的运行模式是 C/S。我们本机是 C,docker 引擎是 S。实际的构建过程是在 docker 引擎下完成的,所以这个时候无法用到我们本机的文件。这就需要把我们本机的指定目录下的文件一起打包提供给 docker 引擎使用。
构建过程中会进行构建日志的打印,出现以下日志则表示构建成功:
Successfully built e4c6e1801984
Successfully tagged HttpServer:v1
4. 常用指令详解
4.1 COPY
复制指令,从宿主机目录中复制文件/目录到容器里的指定路径。
COPY [--chown=<user>:<group>] <源路径> <目标路径>
COPY [--chown=<user>:<group>] ["<源路径>", "<目标路径>"]
参数说明:
-
[--chown=<user>:<group>]
:可选,改变复制到容器内文件的用户和组 -
<源路径>
:源文件/源目录,支持通配符 -
<目标路径>
:容器内的路径,如路径不存在会自动创建
4.2 CMD
类似于RUN
指令,用于运行程序,但二者运行的时间点不同,区别如下:
-
CMD
在docker run
时运行 -
RUN
在docker build
时运行
注意事项如下:
-
CMD
的作用是为启动的容器指定默认要运行的程序,程序运行结束,容器结束 -
CMD
指令指定的程序可被docker run
命令行参数中指定要运行的程序所覆盖 - 如果 Dockerfile 中如果存在多个
CMD
指令,仅最后一个生效
CMD <shell 命令>
CMD ["<可执行文件或命令>","<param1>","<param2>",...]
CMD ["<param1>","<param2>",...] # 该写法是为 ENTRYPOINT 指令指定的程序提供默认参数
推荐使用第二种格式,默认的可执行文件是sh
。
4.3 ENV
设置环境变量,定义的环境变量,在后续就可以使用这个环境变量。
例如我们构建 python 工程的 docker,那么指定 pip 源就可以通过ENV
设置了。
# 设置环境变量
ENV pypi https://pypi.douban.com/simple
# 安装依赖
RUN pip install --no-cache-dir -r requirements.txt flask uwsgi -i ${pypi}
4.4 ARG
构建参数,作用与ENV
一致,但作用域不一样。ARG
设置的环境变量只有docker build
的过程中有效,构建好的镜像内不存在这个环境变量。
构建命令docker build
中可以用--build-arg <参数名>=<值>
来覆盖。
格式:
ARG <参数名>[=<默认值>]
4.5 EXPOSE
用于声明docker内部的端口
- 便于镜像的使用者理解镜像服务的端口,方便配置映射。
- 在运行时使用随机端口映射时,也就是
docker run -P
时,会自动随机映射EXPOSE
的端口。
格式:
EXPOSE <端口1> [<端口2>...]
4.6 WORKDIR
指定工作目录,用WORKDIR
指定的工作目录,会在构建镜像的每一层中都存在。
docker build
构建镜像过程中的,每一个RUN
命令都是新建的一层。WORKDIR
指定的工作目录,必须是提前创建好的,只有通过WORKDIR
创建的目录才会一直存在。
格式如下:
WORKDIR <工作目录路径>
5. 其他指令介绍
5.1 ENTRYPOINT
类似于CMD
的指令,但不会被docker run
的指定参数所覆盖,而且这些命令行参数会被当作参数送给ENTRYPOINT
指令指定的程序。
在docker run
时使用--entrypoint
,可以覆盖CMD
指令指定的程序。
优点:在执行docker run
的时候可以指定ENTRYPOINT
运行所需的参数。
注意:如果 Dockerfile 中如果存在多个ENTRYPOINT
的指令,那么只有最后一个生效。
ENTRYPOINT ["<executeable>","<param1>","<param2>",...]
搭配CMD
命令使用:一般是变参才会使用CMD
,这里的CMD
等于是在给ENTRYPOINT
传参
如果使用以下 Dockerfile 构建镜像:
ENTRYPOINT ["HttpServer", "-p"]
CMD ["10000:5000"]
不传参运行docker run HttpServer:v1
,容器默认执行HttpServer -p 10000:5000
。
传参运行docker run HttpServer:v1 -p 20000:5000
,容器默认执行HttpServer -p 20000:5000
。
5.2 ADD
和COPY
的使用格类似(官方推荐使用COPY
)。
优点:在执行<源文件>
为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到<目标路径>
。
缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。
5.3 VOLUME
定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。
作用:
- 避免重要的数据,因容器重启而丢失。
- 避免容器不断变大。
格式:
VOLUME ["<路径1>", "<路径2>"...]
VOLUME <路径>
在启动容器docker run
的时候,可通过-v
参数修改挂载点。
5.4 USER
用于指定执行后续命令的用户和用户组。
格式:
USER <用户名>[:<用户组>]
5.5 HEALTHCHECK
用于指定某个程序来监控 docker 容器服务的运行状态。
格式:
HEALTHCHECK [选项] CMD <命令>:设置检查容器健康状况的命令
HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令
HEALTHCHECK [选项] CMD <命令> : 这边 CMD 后面跟随的命令使用,可以参考 CMD 的用法。
5.6 ONBUILD
用于延迟构建命令的执行,本次构建镜像的过程中不会执行,当有新的 Dockerfile 使用了之前构建的镜像FROM HttpServer
时,会执行Dockerfile 里的ONBUILD
指定的命令。
格式:
ONBUILD <指令>
5.7 LABEL
LABEL
指令可以给镜像添加一些元数据,以key-value
的形式,格式如下:
LABEL <key>=<value> <key>=<value> <key>=<value> ...
比如添加镜像作者命令如下:
LABEL org.opencontainers.image.authors="xiaoi"