base镜像
base镜像: 1)不依赖其他镜像, 从scratch构建, 2)其他镜像可以以之为基础进行拓展,
能称作base镜像的通常是各种Linux发行版的Docker镜像, 如Ubuntu, Debian, CentOS等
base镜像为何这么小?
Docker支持运行多种LinuxOS
但注意, 所有容器只能公用Host的kernel, 并且不能修改
镜像的分层结构
Docker支持通过拓展现有镜像, 创建新的镜像
容器的Copy-on-Write特性
构建镜像
docker commit
步骤:
- 运行容器
- 修改容器
- 将容器保存为新的镜像
纯手工, 不推荐, 易出错, 效率低可重复性弱, 且无法对镜像进行审计, 存在安全隐患
Dockerfile
Dockerfile是一个文本文件, 记录了镜像构建的所有步骤
Dockerfile常用指令
- FROM, 指定base镜像
- MAINTAINER, 设置镜像作者
- COPY, 将文件从build context复制到镜像
COPY src dest 或 COPY [“src”,”dest”], src只能指定build context中的文件或目录
- ADD, 与copy类型, 从build context中复制文件到镜像, 不同的是, 如果src是归档文件(tar,zip,tgz,xz等), 文件会被自动解压到dest
- ENV, 设置环境变量, 环境变量可被后面的指定使用
- EXPOSE, 指定容器中的进程会监听某个端口, Docker可以将该端口暴露出来
- VOLUME, 将文件或者目录声明为volume
- WORDDIR, 为后面的RUN, CMD, ENTRYPOINT, ADD, COPY指令设置镜像中的当前工作目录
- RUN, 在容器中运行指定的命令
- CMD, 在容器启动时运行指定的命令, 可以有多个, 但只有最后一个生效, CMD可以被docker run之后的参数替换
- ENTRTYPOINT, 设置容器启动时的命令, 可以有多个, 但只有最后一个生效, CMD或docker run之后的参数会被当做参数传递给ENTRYPOINT
RUN vs CMD vs ENTRYPOINT
1)RUN: 执行命令并创建新的镜像层, 常用于安装软件包
Shell格式:RUN
Exec格式: RNU ["executable","param1","param2"]
2)CMD: 设置容器启动后默认执行的命令及其参数, 但CMD能够被docker run 后面跟的命令行参数替换
Exec格式: CMD ["executable","param1","param2"]
CMD ["param1","param2"]为ENTRYPOINT提供额外的参数, 此时ENTRYPOINT必须使用Exec格式
Shell格式: CMD command param1 param2
CMD echo "hello world"
运行docker run -it [image]将输出 hello world
运行docker run -it [image] /bin/bash, CMD将被忽略掉, 命令bash将被执行
3)ENTRYPOINT: 配置容器启动时运行的命令, ENTRYPOINT不会被忽略, 一定会被执行
Exec格式: ENTRYPOINT ["executable","param1","param2"]
用于设置要执行的命令及其参数, 同时可通过CMD提供额外参数, ENTRYPOINT中的参数始终会被使用, 而CMD的额外参数可以在容器启动时动态替换掉
如 ENTRYPOINT ["/bin/echo","hello"] CMD ["world"]
运行docker run -it [image] CloudMan 将输出hello CloudMan
Shell格式: ENTRYPOINT command param1 param2
会忽略任何CMD或docker run 提供的参数
Shell 和Exec格式
Shell格式
<instruction> <command>
如:
RUN apt-get install python3
CMD echo "Hello world"
ENTRYPOINT echo "Hello world"
当指令执行时, shell格式底层会调用 /bin/sh -c [command]
如
ENV name Cloud Man
ENTRYPOINT echo "Hello, $name"
会输出 Hello, Cloud Man
Exec格式
<instruction> ["executable","param1","param2",...]
如:
RUN ["apt-get","install","python3"]
如
ENV name Cloud Man
ENTRYPOINT ["/bin/echo","Hello, $name"]
会输出Hello, $name
环境变量name没有被替换, 如果希望使用环境变量, 应改成
ENTRYPOINT ["/bin/sh","-c","echo Hello, $name"]
CMD和ENTRYPOINT推荐使用Exec格式, 因为指令可读性更强, 更易理解, RUN都行
总结
分发镜像
镜像名构成: [image name]=[repository]:[tag]
使用docker build时没有指定tag, 会使用默认值latest
tag最佳实践
使用公共Registry
- 在Docker Hub注册账号
- docker login -u [name]登录账号
- 修改镜像的repository, 使之与Docker Hub账号匹配
Docker Hub完整镜像格式为 [username]/xxx:tag, 可以通过docker tag重命名镜像
- 通过docker push上传镜像
搭建本地Registry
镜像常用命令
- images
- history
- commit, 从容器创建镜像
- build, 从dockerfile创建镜像
- tag
- pull
- push
- rmi, rmi只能删除host上的镜像, 不会删除registry的镜像, 如果一个镜像对应多个tag, 只有当最后一个tag删除时, 镜像才被真正删除
- search