Docker - Dockerfile - 常见命令简介
-
概述
- 感觉是个 比较重要的东西
-
有个疑问
- 我是先讲 docker build 还是 先讲 Dockerfile
- 穿插讲
-
docker build
- 最基本的东西
- 原理
- -t
- -f
- 最基本的东西
-
docker file
- 各种命令
- 命令本身
- 如果需要 docker build 配合, 那就和 docker build 一起讲
- 各种命令
-
- 穿插讲
- 我是先讲 docker build 还是 先讲 Dockerfile
-
准备
-
os
- centos7
-
docker
- client
- 18.09.6
- engine
- 18.09.6
- client
-
知识
- docker
- docker 镜像
- shell 编程
-
1. Dockerfile
-
概述
- 简介 Dockerfile
-
回顾
- docker 镜像
-
概述
- docker 容器的模板
-
结构
- 由若干个 layer 组成
-
构建容器机制
- 构建时, 自底向上依次构造 layer
- 只读模式
- 向外提供一个读写层
- 构建时, 自底向上依次构造 layer
-
创建方式
-
docker commit
- 概述
- 将当前的容器, 构造成一个镜像
- 概述
-
docker build
- 概述
- 由 Dockerfile, 构建一个镜像
- 概述
-
对比
-
docker commit
- 方便构建
- 但是会缺失一些信息
-
docker build
- 方便管理
- 环境及代码
- 可以用 git 管理
- 方便移动
- 方便修改, 结构清晰
- 环境及代码
- 方便管理
-
-
-
建议
- 尽量用 Dockerfile 构建镜像
-
- docker 镜像
-
Dockerfile
-
概述
- docker 构建镜像的源文件
-
机制
- docker 依次读取 Dockerfile 里的命令
- 指定的环境
- 逐层构建镜像
-
语法
- Dockerfile 语法想对较多
- 这个后面慢慢描述
- Dockerfile 语法想对较多
-
2. docker build
-
概述
- docker client 构造镜像
-
准备
- 一个 Dockerfile
- 记录构建镜像的命令
- 一个上下文
- 准备构建镜像时需要的资源
- 一个 Dockerfile
-
Dockerfile
-
例子
# 最简单的 Dockerfile # 文件名为 Dockerfile FROM ubuntu:14.04 RUN echo 'hello'
-
注意
- Dockerfile 的文件名
-
默认文件名是 Dockerfile
- 如果首字母没有大写, docker 可能会找不到文件
- 如果硬要执着名字, 需要 -f 参数来制定
- 这个后面会讲
-
Dockerfile 里的 命令, 一定要 大写
- 小写了 docker 不认识
-
- Dockerfile 的文件名
-
-
docker build
-
概述
- 构建镜像的命令
- 这里简单讲下使用
- 其他的参数, 后面会跟 Dockerfile 的语法一起讲
-
准备
-
context
- 作用
- 存放 Dockerfile
- 存放 image 需要的其他文件
- 作用
-
Dockerfile
- 作用
- 构建镜像的说明书
- 作用
-
其他
- 执行命令时, 需要进入 context 目录
-
-
命令执行
-
最简单的那种
-
命令
# 是的, 你没看错, 这就完了... # 格式: docker build <context> > docker build .
-
结果
- 镜像生成成功
-
问题
- 生成的镜像, 没有 仓库 和 tag 信息, 很难定位
-
-
添加 仓库信息 定位
-
命令
# -t 选项, 可以提供 标签 的配置 # 格式: docker build -t <repo>[:tag] <context> > docker build -t myrepo/image:0.0.1 .
-
结果
- 镜像生成成功
- 带有 repo 和 tag 信息
-
-
自定义 Dockerfile 和 context
-
命令
# 手动指定 Dockerfile 和 context # 格式: docker build -t <repo>[:tag] -f <DockerfilePath> <context> > docker build -t myrepo/image:0.0.2 -f /root/myDockerfile /root/context
-
结果
- 镜像生成成功
- 使用的是 指定的资源
-
-
-
-
执行结果
-
结果
> docker build -t <repo>/demo:0.0.2 -f Dockerfile . Sending build context to Docker daemon 2.048kB Step 1/2 : FROM ubuntu:latest ---> 7698f282e524 Step 2/2 : RUN echo 'hello' ---> Using cache ---> 331b9ab46190 Successfully built 331b9ab46190 Successfully tagged <repo>/demo:0.0.2
-
3. Dockerfile 命令简介
- 概述
- 简单介绍命令
1. 注释
-
概述
- Dockerfile 的注释
-
格式
# 以 # 开头的行 # 行中出现的 # 则一律不被视为 注释 # 注释不支持 换行
-
特殊注释
-
概述
- 有部分特殊的注释, 会影响 Dockerfile 的构建
-
注意
- 一类特殊注释, 只能出现一次
- 出现的位置, 必须在 FROM 语句之前
- 而且格式必须 符合要求, 否则就是 普通注释
- 不能换行
- 不能随便加空格
-
后跟一个空格
- = 前后没有空格
- 下面给的例子, 肯定没问题
-
-
syntax
-
概述
- Dockerfile 语法指定
-
例子
# syntax=docker/dockerfile
-
其他
- 需要有 BuildKit 的支持
- 默认是 docker/Dockerfile
- 具体可用版本, 请查询官方文档
-
-
escape
-
概述
- 指定 转义字符 符号
- 这个名字叫啥, 我也不确定
- 指定 转义字符 符号
-
转义字符
- 默认
- \ 开头, 后面的一个字符会被转义
- 设置
- 可以配置成其他的
- windows 环境下, 常用 `
- 默认
-
例子
# 这个例子 # escape=`
-
-
2. FROM
-
概述
- 指定一个 基础镜像
-
基础镜像
-
概述
- 在某个镜像的基础上, 再构建镜像
-
作用
- 方便构建
- 省去基础的准备
- 加快速度
- 构建直接从新内容开始
- 基础层沿用基础镜像的内容
- 发展快速
- 你的构建, 也可以成为别人构建的基础
- 方便构建
-
-
示例
FROM ubuntu:latest
-
其他
-
通常在 Dockerfile 第一句
- 例外
- 注释
- 常规注释
- syntax
- escape
- arg
- 指定参数
- 注释
- 例外
-
from 一定要大写
-
tag
- 最好指定明确版本, 不要用 latest
-
3. ARG
-
概述
- 给 指定镜像参数
-
参数
- 镜像在 构建中 使用的变量
- 构建完成后就会 无效
- 构建中如果声明了 同名的环境变量, 就会被 替代
- 环境变量后面会提到
-
示例1: 定义一个变量, 用来定义 基础镜像的版本
-
Dockerfile
# Version 0.0.4 ARG version FROM ubuntu:$version
-
命令
# 通过 --build-arg 指定了 version 参数 # -f 指定了 Dockerfile > docker image build --build-arg version=19.04 -t repo/demo:0.0.4 -f Dockerfile04 .
-
结果
-
构建成功
-
版本正确
> docker image inspect -f '{{.RepoTags}}' repo/demo:0.0.4
-
-
其他
- 构建中
- 命令行中的 step 里, 看到的还是 $version
- 构建中
-
问题: 万一我忘了加参数, 会怎么样呢
-
结果
- 生成会报错
-
有没有什么好办法呢
- 当然有啦, 加默认值
-
-
-
示例2: 为 arg 添加默认值
-
Dockerfile
# Version 0.0.5 ARG version=19.04 FROM ubuntu:${version}
-
命令
> docker image build -t repo/demo:0.0.5 -f Dockerfile05 .
-
结果
- 创建成功
-
问题1: 如果我又想指定值了, 有办法吗?
- 当然有啦
- 还是用 --build-arg 指定
- 当然有啦
-
问题2: 这个 arg 除了指定 from 的版本信息, 还能干别的吗?
- 也可以在其他地方用啊
- 马上就开始讲了
- 也可以在其他地方用啊
-
-
示例3: arg 的其他使用
-
Dockerfile
# Version 0.0.6 ARG version=19.04 FROM ubuntu:${version} RUN echo ${version}
-
命令
> docker image build -t repo/demo:0.0.6 -f Dockerfile06 .
-
结果
- 镜像成功创建
- echo 那行, 却没有显示出 版本号
-
问题1: 为什么版本号不见了?
-
结果
- 作用域问题
- from 前面的 arg, 作用域只能到 from 语句
- 之后就消失了
- ref
- 作用域问题
-
后续
-
如何使用 from 前的 arg
-
重新声明即可
# Version 0.0.7 ARG version=19.04 FROM ubuntu:${version} ARG version RUN echo "hello ${version}"
-
-
或者说, 在 from 后面使用 arg
-
再者, 还可以直接使用 env
-
-
-
-
问题: 既然在 构建完就无法使用了, 能不能用来存放 密码 之类的东西
- 不建议
- 虽然重新起来的容器看不到了
- 但是可以通过 'docker image history' 查看这个东西
- 不建议
-
预定义 arg
-
概述
- docker 预定义了一些 变量
-
列表
# 本质上只有 四个 # 具体干啥, 我现在还不知道 # 但是乍一看, 是跟 网络相关的 # 这个等以后有机会, 再讲吧 HTTP_PROXY http_proxy HTTPS_PROXY https_proxy FTP_PROXY ftp_proxy NO_PROXY no_proxy
-
4. ENV
-
概述
- 镜像对应容器的 环境变量
-
环境变量
-
概述
- 由镜像启动容器后, 默认会带一些 环境变量
-
作用
- 环境变量可以改变环境的很多东西
- 或者说, 改变环境变量, 就能改变系统行为
- 而且环境变量这种东西, 一般是 所有用户 都能获取到的
- 环境变量可以改变环境的很多东西
-
-
示例1: 简单使用 环境变量
-
Dockerfile
# Version 0.0.8 ARG version=19.04 FROM ubuntu:${version} ARG version RUN echo "hello ${version}" ENV var="docker" RUN echo "hello ${var}"
-
命令
> docker image build -t repo/demo:0.0.8 -f Dockerfile08 .
-
结果
- 镜像创建成功
- 变量成功使用
-
问题1: 为啥这次一上来就设置 env 的默认值, 不设置可以吗?
-
当然可以啦
- 但是, 弥补时机, 不太一样
-
弥补时机
- arg
- docker image build
- --build-arg
- docker image build
- env
- docker container run
- -e / --env
- 这个后面应该会 找机会讲, 还是有点用的
- docker container run
- arg
-
-
问题2: 会不会有这种场景, 我的某个 arg 和 env, 值其实是一样的
-
场景
- arg 和 env 值是一样的
- 我想在 build 时确认, 以免 后面忘了
-
当然可以
- arg 和 env 可以联动的
-
-
-
示例2: arg 联动 env
-
Dockerfile
# Version 0.0.9 ARG version=19.04 FROM ubuntu:${version} ARG version RUN echo "hello ${version}" ENV var=${version} RUN echo "hello ${var}"
-
命令
> docker image build -t repo/demo:0.0.9 -f Dockerfile09 .
-
结果
- 镜像正常产生
- var 也被赋予了 verison 的值
-
其他
- 在这种场景下, env 甚至可以和 arg 重名
- 结果
- env 被赋予 arg 的值
- arg 就没了
- 结果
- 在这种场景下, env 甚至可以和 arg 重名
-
问题1: env 可以取消吗
- 这个在 shell 里是可以的
- 但是 Dockerfile 里, 是否有, 我暂时还没找到...
-
5. run
-
概述
- 执行命令
-
执行
- 表面
- 执行命令
- 实际
- 将上一层的镜像, 启动为一个容器
- 在容器里执行命令
- 将执行命令后的容器, 再整成一层新的镜像
- 表面
-
模式
-
shell 模式
-
概述
- 启动一个 shell, 然后执行命令
-
默认shell
- linux
- /bin/sh -c
- win
- cmd /S /C
- linux
-
切换 shell
- 这个可以通过后面的 SHELL 命令来做
-
命令
# RUN <command> [<options and args>] RUN echo "hello, docker."
-
-
exec 模式
-
概述
- 不启动 shell, 直接执行命令
-
不启动 shell
-
这个我也看不懂
- 官网说的很模糊
- 强调的, 也只有 exec 模式取不到 环境变量
-
好吧, 那我就理解为
- 取不到 环境变量
- 原因可能是害怕某种干扰吧
-
-
命令
# 1. 使用 json 的 数组格式 # 2. 命令和参数作为数组的成员 # 3. 空格隔开的, 就是一个参数 # 4. 每个参数, 都要用 "" 引起来 RUN ["echo", "hello, docker."] # 如果硬要 环境变量 RUN ["/bin/sh", "-c", "echo", "hello, docker."]
-
-
-
建议
- 加速
- 因为执行一个 run, 会生成一个容器和镜像
- run 越多, 构造时间就越长
- 解决
-
将多个命令, 写到一个 run 里
FROM ubuntu:16.04 RUN apt-get update \ && apt-get install -y curl \ && rm -rf /var/lib/apt/lists/*
-
- 因为执行一个 run, 会生成一个容器和镜像
- 加速
6. shell
-
概述
- 指定 运行命令 的 shell
-
shell
-
默认 shell
- 上一部分提过
-
切换 shell
- Dockerfile 中可以随时切
-
问题
- 切换 shell, 会不会导致 环境变量 丢失
-
-
命令
# linux SHELL ["/bin/bash"] # win SHELL ["powershell", "-command"]
7. copy
-
概述
- 将文件从 宿主机 拷贝到 镜像
-
拷贝
-
源
- 拷贝的源, 必须在 context 下
- 所以路径信息, 都是 以context为根 的路径
- 内容
- 文件
- 目录
- 原内容支持 通配符
- 通配符 不是 正则表达式
- 解压
- 不会做
- 拷贝的源, 必须在 context 下
-
目的
-
拷贝的目的
- 文件
- 结尾不带 /
- 目录
- 结尾带 /
- 文件
-
路径
- 如果路径不存在, 会自动创建
-
-
dest 文件权限
-
默认
- uid 和 gid 都为 0
-
命令
# 官网上给的例子 # 其他的搭配, 估计只有自己尝试了... --chown=<userId>:<groupName> --chown=<userName> --chown=<userId> --chown=<userId>:<groupId>
-
-
权限
- 默认 0755
- 这个需要用 命令 改
- 默认 0755
-
-
命令
COPY [--chown=<user>:<group>] <src> ... <dest>
8. add
-
概述
- 将文件拷贝到 镜像
- 来源丰富
- 可以解压
- 将文件拷贝到 镜像
-
拷贝
-
源
-
拷贝的源
- context 下, 同 copy
- url
-
解压
- 不会做
-
其他
- 同 copy
-
-
目的
-
解压
- 源是 压缩包
- gz 等
- 需要去 官网 确认
- 目的
- 一个 目录
- 如果目的有同名文件
- 不会覆盖
- 源是 压缩包
-
其他
- 同 copy
-
-
dest 文件归属
- 同 copy
-
权限
- 默认 0755
- 这个需要用 命令 改
- 默认 0755
-
-
命令
# 从 url 获取(不解压) ADD http://wordpress.org/latest.zip /root/wordpress.zip # 解压 ADD http://wordpress.org/latest.zip /root/wordpress/
9. cmd
-
概述
- 容器启动命令
- 配合 entrypoint
- 这个后面再说
-
启动命令
-
启动命令
-
时机
- 容器启动时执行的命令
-
只会有 一个
- 所以 cmd 命令只有 最后一个 会生效
-
替代
- 如果 docker run 指定了 启动命令的话
- cmd 的命令, 不会再执行
- 如果 docker run 指定了 启动命令的话
-
-
执行模式
-
shell 模式
-
命令
# 类似 RUN CMD command param1 param2
-
-
exec 模式
``` # 类似 RUN CMD ["executable","param1","param2"] ```
-
-
docker run
- 没有命令
- 执行 cmd
- 有 命令
- 执行 docker run 的命令
- 没有命令
-
10. entrypoint
-
概述
- 优先级更高的 启动命令
- 配合 cmd 可以指定 命令的默认参数
-
启动命令
-
工作模式
- shell 模式
- 同 run
- exec 模式
- 同 run
- shell 模式
-
单独使用 entrypoint
- 同 单独使用 cmd
-
配合使用
-
entrypoint
- 使用 exec 模式
- 第一个参数为, 可执行命令
- 后面的参数, 为 稳定的参数 或者 选项
- 使用 exec 模式
-
cmd
- 使用 exec 模式
- 所有参数, 都是 entrypoint 的 参数
- 如果 cmd 可以执行, 则会 覆盖 entrypoint
- 使用 exec 模式
-
-
docker run
- 没有命令
- 执行 entrypoint + cmd
- 有命令
- 执行 entrypoint + docker run 后面跟的 参数
- 没有命令
-
-
ref
11. label
-
概述
- 添加 描述信息
-
描述信息
- 镜像元数据
-
命令
LABEL maintainer='repo'
-
查看
> docker image inspect -f '{{json .ContainerConfig.Labels}}' repo/demo:0.0.1
12. user
-
概述
- 指定默认用户
-
默认用户
-
默认执行命令的用户
-
默认值
- root
-
命令
USER <user>[:<group>] USER <UID>[:<GID>]
-
13. workdir
-
概述
- 指定默认目录
-
默认目录
-
docker 启动后的 pwd
- 命令如果不指定路径, 都会以 那里为 pwd
-
默认值
- /root/
-
路径
-
绝对路径
- / 开头
-
相对路径
- 直接是 路径开头
- 相对的是 上一个 workdir
- 直接是 路径开头
-
可以解析环境变量
-
如果指定到一个 空路径
- 会主动创建
-
-
命令格式
WORKDIR /absolutePath WORKDIR relativePath
-
14. onbuild
-
概述
- 触发器
-
触发器
-
触发场景
- 该镜像察觉到自己作为其他镜像的 基础镜像
-
结果
- 执行以 ONBUILD 开头的命令
- 可以理解为 在 from 语句后, 按顺序执行 onbuild 语句
- 然后再执行 Dockerfile 里的语句
- 执行以 ONBUILD 开头的命令
-
-
命令
ONBUILD <otherInstruction>
15. volume
-
概述
- 添加 挂载点
-
挂载点
-
概述
- 一个路径
- 但这个路径下, 会 挂载一个 卷
-
机制
- Dockerfile
- 指定挂载点
- 创建镜像
- 生成容器
-
默认行为
- 在 host 生成一个 卷
- 卷名随机
- 将这个卷挂载到 容器的挂载点
- 在 host 生成一个 卷
-
-v
- 将 -v 指定的内容, 对接到挂载点
-
- Dockerfile
-
其他
- 如果 路径不存在, 会在容器里创建
-
-
命令
# 列表式 VOLUME /myvol /root/test # json 式 VOLUME ["/myvol", /root/test]
16. expose
-
概述
- 暴露 容器端口
-
暴露容器端口
-
概述
- 指定某个容器端口
- 让这个端口 在默认的情况下, 暴露出来
-
暴露
- 对容器外可见
-
机制
- expose 某个端口
- 启动容器
-
-
命令
# 指定端口和协议 # 默认协议是 tcp # 可以指定 多个 expose <port>[:<protocol>]
-
创建容器
# 一定要加 -P # 这样 expose 的端口, 会随机映射到 host 的可用端口上 # 如果没有, 则会别 映射到 null # 不影响 -p 选项来暴露端口 > docker container run --rm --name demo03 -it -P -p 32769:90/tcp repo/demo:0.0.1
-
验证
# 可以在 ports 那里, 看到暴露端口 > docker container ls
17. healthcheck
-
概述
- 健康检查
-
健康检查
-
机制
- 定期在容器中 执行命令,
- 根据 执行结果 判断容器是否健康
- 将健康情况, 反馈到
docker container ps
的 status 栏里
-
执行机制
-
参数
- 时间间隔
- --interval
- 默认值 30 s
- 超时时间
- --timeout
- 默认值 30s
- 重试次数
- --retries
- 默认值 3
- 时间间隔
-
健康状态
- starting
- 开始状态
- healthy
- 健康状态
- unhealthy
- 不健康状态
- starting
-
注意
- 一个镜像, 只能有一个 生效的 checkhealth
- 如果当前 Dockerfile 里没写, 会继承父镜像的
- 如果 当前 和 父镜像都有, 则以当前为准
-
-
命令
# 拒绝继承, CHECKHEALTH NONE # 简单示例 # 注意, 那个 CMD 是格式, 跟 CMD 命令要区别开 # curl 如果失败, 则容器状态变为 不健康 checkout --interval=10s --timeout=3s --retries=3 CMD curl http://192.168.30.5:5000/v2
-
ps
-
ref
- Dockerfile reference
- docker build
- Dockerfile HEALTHCHECK详解
- 书籍
- 第一本 docker 书(修订版)
- docker 容器与容器云
- spring 微服务实战
- docker 实践
-
后续
-
整理
- 花了一晚上整理的内容, 感觉还是有点乱
- 想把它 拆开
- 放一块的话, 内容可能会不全
-
搭建一些环境, 稍微实战一下
-
学习容器编排
- compose
- k8s
-