前言
在上一节《轻松掌握Docker使用-基础入门(一)》中我们了解到:
- Docker是什么?
- Docker的镜像管理&基础命令
- Docker容器的基本操作
这一节,我们来学习: - 如何定制Docker镜像?
使用 Dockerfile 定制镜像
什么是Dockerfile?
我们先来了解下什么是Dockerfile:
Dockerfile 是一个文本文件,其内包含了一条条的 指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。
简单来说就是,一个形容如何构建镜像的文本文件,而文件中包含了一条条的指令,通过指令告诉docker想构建出怎样的镜像。
Dockerfile“初使用”
这里我们自定义个 首页为“Hello, Docker!”的nginx镜像。
- 创建Dockerfile文件
~]# mkdir -p docker/custom-images
~]# cd docker/custom-images/
custom-images]# ls
custom-images]# mkdir mynginx
custom-images]# ls
mynginx
custom-images]# cd mynginx/
mynginx]# touch Dockerfile
mynginx]# ls
Dockerfile
- 编写Dockerfile
FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
Dockerfile 支持 Shell 类的行尾添加 \ 的命令换行方式,以及行首 # 进行注释的格式。
- 根据Dockerfile构建镜像
docker根据Dockerfile构建镜像的命令格式如下:
docker build [选项] <上下文路径/URL/->
mynginx]# docker build -t mynginx:v1 .
Sending build context to Docker daemon 2.048kB
Step 1/2 : FROM nginx
latest: Pulling from library/nginx
a330b6cecb98: Pull complete
e0ad2c0621bc: Pull complete
9e56c3e0e6b7: Pull complete
09f31c94adc6: Pull complete
32b26e9cdb83: Pull complete
20ab512bbb07: Pull complete
Digest: sha256:853b221d3341add7aaadf5f81dd088ea943ab9c918766e295321294b035f3f3e
Status: Downloaded newer image for nginx:latest
---> ad4c705f24d3
Step 2/2 : RUN echo 'Hello, Docker!' > /usr/share/nginx/html/index.html
---> Running in f084b7333da2
Removing intermediate container f084b7333da2
---> e8edfb8313a0
Successfully built e8edfb8313a0
Successfully tagged mynginx:v1
其中 docker build -t mynginx:v1 .
中-t
指定了镜像的名称,而.
指定的是上下文目录,docker build 命令会将该目录下的内容打包交给 Docker 引擎以帮助构建镜像。
4. 使用新构建的镜像运行容器
mynginx]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mynginx v1 e8edfb8313a0 4 minutes ago 133MB
[root@iZuf6aoqssezcm3p2u4jlkZ mynginx]# docker run --rm -it mynginx:v1 bash
root@a88f0c44629c:/# cat /usr/share/nginx/html/index.html
Hello, Docker!
Dockerfile常用指令说明
FROM 基础镜像
格式:FROM 镜像名称
我们可以使用FROM
指令,基于某一镜像来构建新的镜像。在Dockerfile中第一条指令必须是FROM
指令。如果想从一个空白镜像构建,那么我们可以使用:
FROM scratch
scratch
是一个虚拟的概念,表示的是一个空白的镜像。
RUN 执行指令
格式:RUN 命令
运行指定命令。
WORKDIR 指定工作目录
格式:WORKDIR <工作目录路径>
使用WORKDIR可以指定后续Dockerfile指令的工作目录,如该目录不存在,WORKDIR 会帮你建立目录。
USER 指定当前用户
格式:USER <用户名>[:<用户组>]
切换当前用户,在切换前需确保指定用户是存在的。USER
指定用户后,后续执行 RUN
, CMD
以及 ENTRYPOINT
这类命令都使用的是该用户。
COPY 复制文件
格式:
-
COPY [--chown=<user>:<group>] <源路径>... <目标路径>
-
COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]
COPY 指令将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置。目标路径不需要事先创建,如果目录不存在会在复制文件前先行创建缺失目录。
CMD 容器启动命令
格式:CMD ["可执行文件", "参数1", "参数2"...]
CMD 指令就是用于指定默认的容器主进程的启动命令的。**使用镜像运行容器,容器内需要有主进程运行容器才能持续运行的状态。容器是为了主进程而存在,如果容器的主进程退出,那么容器也失去意义从而退出。**这一点也是提醒我们,如果想让容器保持运行那么CMD
执行的容器启动命令需要hang住主进程,而不是执行完主进程立马退出。
ENTRYPOINT 入口点
格式:ENTRYPOINT ["可执行文件", "参数1", "参数2"...]
ENTRYPOINT
和CMD
的用法一致,目的也是用于指定容器主进程的启动命令。同样在运行容器的时候,指定命令从而覆盖ENTRYPOINT
或CMD
中指定的命令。不同的是在运行容器时要覆盖ENTRYPOINT
中指定的命令,需要使用--entrypoint
参数进行覆盖。
使用ENTRYPOINT
指令之后,再使用CMD
指令,那么CMD
指令指定的参数将作为ENTRYPOINT
指令的参数。使用ENTRYPOINT
指令之后,运行容器时指定运行参数,则同样也是作为ENTRYPOINT
指令的参数。
ENV 设置环境变量
格式:ENV <key1>=<value1> <key2>=<value2>...
使用ENV
设置环境变量后,后续的RUN
等指令,还是运行时的应用,都可以使用${变量名}
使用到变量值。
EXPOSE 暴露端口
格式:EXPOSE <端口1> [<端口2>...]
声明运行时容器提供服务端口,这只是一个声明,在运行时并不会因为这个声明应用就会开启这个端口的服务。当在docker run -P
运行容器开发随机端口时,将会自动随机映射EXPOSE
的端口。
参考资料