前言
在之前的博客《Docker 端口映射及创建镜像演示 (二)-- 技术流 ken》, 演示了如何使用一个现有容器创建一个镜像, 以及镜像在阿里云的上传和下载.
但是这样的镜像有很大的局限性, 不能根据我们的生产需要进行个性化定制, 所以我们急需学习一种能够满足我们需要的制作镜像的工具.
这个时候 Dockerfile 就出现了.
使用 dockerfile 指令可以根据自己的需要, 制作满足自己生产需要的镜像.
本篇博客将详细讲解如何使用 dockerfile 制作自己的专属镜像.
Dockerfile 简介
镜像的定制实际上就是定制每一层所添加的配置, 文件. 如果我们可以把每一层修改, 安装, 构建, 操作的命令都写入一个脚本, 用这个脚本来构建, 定制镜像, 那么哪些无法重复的问题, 镜像构建透明性的问题, 体积的问题就都会解决. 这个脚本就是 Dockerfile.
Dockerfile 是一个文本文件, 其内包含了一条条的指令, 每一条指令构建一层,
因此每一条指令的内容, 就是描述该层应当如何构建
Dockerfile 编写注意项
# 备注
指令参数, 指令的大小写不敏感
第一个非注释行必须是 FROM 指令
编写 Dockerfile 必须在一个目录下进行, 这个目录称之为 工作目录 (WORKSPACE)
Dockerfile 文件命令的首字母必须大写
制作镜像所要用的文件必须放在工作目录或者工作目录的子目录之下, 不能放在父目录
可以通过隐藏文件 .dockeringnore 来指定不要放入到镜像中的文件, 一行是一个文件, 可以用通配符
基于 dockerfile 做镜像, 本质上还是基于一个现有的镜像做新镜像
Dockerfile 指令详解
1. FROM
作用: FROM 就是指定基础镜像, 因此一个 Dockerfile 中 FROM 是必备的指令, 并且必须是第一条指令
格式:
- FROM <registry>:[tag]
- FROM <registry>@<digest>
FROM 示例:
第一步: 创建工作目录及 dockerfile
- [root@ken ~]# mkdir /ken
- [root@ken ~]# cd /ken
- [root@ken ken]# touch Dockerfile
第二步: 写入 from 指令
docker.io: 注册表
nginx: 仓库
latest: 版本号
- [root@ken ken]# cat Dockerfile
- FROM docker.io/nginx:latest
- 2. LABEL
作用: 设定一些元数据
格式:
LABEL 信息
LABEL 示例:
- LABEL author "ken"
- 3. COPY
作用: 将工作目录下的文件复制到所做得镜像中的文件系统中
格式:
复制单个文件: COPY <src> <dest>
复制多个文件: COPY [<src> <src> <src>... <dest>]
COPY 示例:
COPY passwd /data/
注意:
源文件路径用相对路径, 目标一般用绝对路径
也可以通配符
源文件必须在工作目录或者工作目录的子目录中
目标路径可以不存在, 会自动创建
如果源文件是一个目录, 会自动递归复制目录下的文件到目标位置, 但是目录自身不会复制
如果复制多个文件, 或者源文件中用了通配符, 那么目标路径必须以 / 为结尾
4. ADD
作用: 和 COPY 类似, 可以实现将文件和目录加载镜像中, 但是区别是可以实现将 tar 包解压, 也可以实现从网络下载文件到镜像
注意: 下载的 tar 无法解压
格式
- ADD <src> <dest>
- ADD ["<src>" "<src>" "<src>" "<dest>"]
ADD 示例:
- ADD nginx-1.14.0.tar.gz /data/
- 5. WORKDIR
作用: 相当于执行 cd 命令. 切换目录, 为后续的 RUN,CMD,ENTRYPOINT 指令配置工作目录.
格式:
WORKDIR 容器目录
WORKDIR 示例:
- WORKDIR /pack/nginx/
- 6. VOLUME
作用: 指定数据卷的挂载点
格式:
VOLUME 容器目录
VOLUME 示例:
- VOLUME /data/MySQL/mysql3306/data
- 7. EXPOSE
作用: 设置 Docker 容器内部暴露的端口号, 如果需要外部访问, 还需要启动容器时增加 - p 或者 - P 参数进行分配.
格式:
EXPOSE PORT/[PROTOCOL]
EXPOSE 示例:
- EXPOSE 80/tcp
- 9. ENV
作用: 设置环境变量
格式:
- ENV var value
- ENV var1=value1 var2=value2 ...
注意:
通过 ENV 所定义的变量是可以传递到容器之中, 但是, 在创建容器的时候, 如果手动指定了变量的值, 那么这个值会覆盖掉镜像中原有的值
ENV 示例:
- ENV pkgname=nginx-1.14.0.tar.gz root=/data/MySQL/mysql3306/data
- 10. RUN
作用: 基于镜像构建容器时候要执行命令
阶段: 第一阶段, 也就是构建镜像的时候执行
格式:
RUN 命令
RUN 示例:
- RUN tar xf $root$pkgname
- 11. CMD
作用: 定义容器启动以后要默认运行的程序, pid 为 1 的程序
阶段: 第二阶段, 也就是将镜像构成成容器的时候执行
注意: 可以在启动容器的时候用指定的命令替换掉镜像所要执行的命令
CMD 指定容器启动是执行的命令, 每个 Dockerfile 只能有一条 CMD 命令, 如果指定了多条, 只有最后一条会被执行. 如果你在启动容器的时候也指定的命令, 那么会覆盖 Dockerfile 构建的镜像里面的 CMD 命令
格式:
CMD < 命令 > 相当于执行的是 / bin/sh -c 命令, 也相当于执行 exec 来运行命令
CMD ["< 命令 >", "< 参数 >", "< 参数 >"]
CMD ["< 参数 >", "< 参数 >"] <<< 需要借助于 ENTRYPOINT 指令
CMD 示例:
- CMD mkdir /ken
- 12. ENTRYPOINT
作用: 定义容器启动以后要默认运行的程序, pid 为 1 的程序
注意:
在运行 RUN 的时候所执行的命令无法覆盖 ENTRYPOINT 中的命令
RUN 后面的命令会被以参数的方式追加到原本要执行的命令的末尾, 而不是替换
基于一个镜像, 在创建容器的时候, 通过传递不同的参数实现创建不同的容器
每个 Dockerfile 中只能有一个 ENTRYPOINT, 当指定多个时, 只有最后一个起效
格式:
ENTRYPOINT ["执行命令","参数 1","参数 2"...]
ENTRYPOINT 示例:
- ENTRYPOINT [ "curl", "-s", "http://10.220.5.138" ]
- 13. ARG
作用: 定义变量, 这个变量是用在第一阶段 (构建镜像 --build)
格式:
ARG 变量名 = 变量值
ARG 示例:
ARG name=ken
补充: Dockerfile 中 ENV 和 ARG 的区别
在指定 docker build 过程中传参数, 要用 ARG
在执行 docker run 的过程中传参数, 要用 ENV
ARG 构建参数和 ENV 的效果一样, 都是设置环境变量. 所不同的是, ARG 所设置的构建环境的
环境变量, 在将来容器运行时是不会存在这些环境变量的
14. USER
作用: 指定运行容器时的用户名和 UID, 后续的 RUN 指令也会使用这里指定的用户
该用户必须存在于容器的用户空间中 (容器的文件系统的中的 / etc/passwd 中)
格式:
USER <UID>|<USERNAME>
USER 示例:
- user ken
- 15. HEALTHCHECK
作用: docker daemon 检查 docker 容器是否正常, 如果异常会将该容器 stop
将容器 stop 的条件
1) 主进程停止了
2) 主进程工作在了后台
格式:
- HEALTHCHECK [options] CMD
- options
- --interval=#s|m 指定健康检查的时间间隔 (例如: 30s,30m)
- --timeout=#s|m 指定等待响应的超时时间
- --start-period=#s|m 指定容器启动多久以后才可以做监控检查
- --retries=# 指定重试次数
返回值
- success
- unhealth
HEALTHCHECK 示例:
- HEALTHCHECK --interval=5m --timeout=1s --retries=3 CMD curl http://10.220.5.138/ken.html || exit 1
- 16. SHELL
可以用来指定系统中默认的 shell 类型
格式:
SHELL ["/bin/sh", "-c"] (Linux 系统中)
SHELL 示例:
- SHELL ["/bin/sh","-c"]
- 17. STOPSIGNAL
向容器中 pid 为 1 的进程发送一个信号, 通过这个信号来关闭这个主进程
默认是 15 信号
格式:
STOPSIGNAL 数值
STOPSIGNAL 示例:
- STOPSIGNAL 9
- 18. ONBULID
作用: 定义一个触发器, 指定的命令在构建镜像时并不执行, 用来实现当基于这个这个镜像做新镜像的时候要执行的命令
格式:
ONBUILD 其他指令
ONBUILD 示例:
ONBUILD COPY ken /App/
Dokcerfile 完整演示创建 nginx 镜像
根据上面各个指令的介绍, 我就直接用上面写的 dockerfile 进行演示. 整个 dockerifle 内容如下.
- [root@ken ~]# VIM /ken/Dockerfile
- FROM docker.io/nginx:latest
- LABEL author "ken"
- COPY ./passwd /data/
- WORKDIR /pack/nginx/
- ENV pkgname=nginx-1.14.0.tar.gz root=/data/MySQL/mysql3306/data/
- COPY nginx-1.14.0.tar.gz $root
- VOLUME $root
- EXPOSE 80/tcp
- RUN tar xf $root$pkgname
- CMD nginx -g "daemon off;"
第一步: 构建镜像
build: 是指根据 dockerfile 制作镜像
-t: 指定一个 tag 标签
.: 表示上下文. 你也可以理解为 dockfile 所在的目录, 但是并不是准确的
如果下方出现 successfully 就表示镜像已经构建成功了
- [root@ken ken]# docker build -t ken:v1-0 .
- Sending build context to Docker daemon 1.021 MB
- Step 1/10 : FROM docker.io/nginx:latest
- ---> 568c4670fa80
- Step 2/10 : LABEL author "ken"
- ---> Using cache
- ---> 80e4e5846fd9
- Step 3/10 : COPY ./passwd /data/
- ---> Using cache
- ---> 685a7ceb74b3
- Step 4/10 : WORKDIR /pack/nginx/
- ---> Using cache
- ---> 0fc65f8c36df
- Step 5/10 : ENV pkgname nginx-1.14.0.tar.gz root /data/MySQL/mysql3306/data/
- ---> Using cache
- ---> 3f6038473472
- Step 6/10 : COPY nginx-1.14.0.tar.gz $root
- ---> Using cache
- ---> 0cbff6223d5b
- Step 7/10 : VOLUME $root
- ---> Using cache
- ---> b74ac1c36c31
- Step 8/10 : EXPOSE 80/tcp
- ---> Using cache
- ---> 6863a87a61a2
- Step 9/10 : RUN tar xf $root$pkgname
- ---> Using cache
- ---> b32ac636a389
- Step 10/10 : CMD nginx -g "daemon off;"
- ---> Running in 02308825301d
- ---> 4a91d70a57eb
- Removing intermediate container 02308825301d
- Successfully built 4a91d70a57eb
第二步: 查看镜像
可以发现构建的名为 ken 标签为 v1-0 的镜像已经存在了
- [root@ken ken]# docker image ls
- REPOSITORY TAG IMAGE ID CREATED SIZE
- ken v1-0 4a91d70a57eb 21 minutes ago 116 MB
第三步: 启动容器
可以发现基于我们刚才的创建的镜像的容器已经顺利跑起来了.
- [root@ken ken]# docker run -d --name ken3 -d ken:v1-0
- 11f492a28b943e619b0ed5d6b19f212f1c9cc47f9bdbe132845e7a7129e5b419
- [root@ken ken]# docker container ps
- CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
- 11f492a28b94 ken:v1-0 "/bin/sh -c'nginx..." 16 seconds ago Up 11 seconds 80/tcp ken3
第四步: 登录容器
可以发现我们这个启动的容器里面已经有我们指定的工作目录
复制过来的 passwd 文件
已经下载并传送到 / data 下了
- [root@ken ken]# docker exec -it ken3 bash
- root@11f492a28b94:/pack/nginx# ls /data/
- MySQL/ passwd
- root@11f492a28b94:/pack/nginx# ls /data/
- MySQL/ passwd
- oot@11f492a28b94:/pack/nginx# ls /data/MySQL/mysql3306/data/nginx-1.14.0.tar.gz
- /data/MySQL/mysql3306/data/nginx-1.14.0.tar.gz
这样基于 dockerfile 自主创建镜像的过程就演示完了, 快去自己制作一个属于自己的镜像吧.
来源: https://www.cnblogs.com/kenken2018/p/10040805.html