Docker 最佳实践
学习地址:Docker - 从入门到实践
- Dockerfile
- 分层存储
- 镜像
- 容器
- 仓库
docker 命令总览,能够看懂这张图的命令就可以了,具体用法可以使用 --help 来查看。

一、基本概念
镜像
操作系统分为内核和用户空间。
Docker 镜像 是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等
docker pull 使用
$ docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]
docker pull ubuntu:18.04
等于
docker pull docker.io/libarary/ubuntu:18.04
docker run
docker run -it --rm ubuntu:18.04 bash
* -i 交互操作
* -t 终端
* --rm 容器退出之后立即删除
* -P 表示将 Dockerfile 中通过 EXPOSE 暴露出来的端口绑定到一个随机的端口
* -p 绑定指定端口

docker image
REPOSITORY | TAG | IMAGE ID | CREATE | SZIE
# 查看镜像、容器、数据卷所占用的空间。
docker system df
- docker image prune
- docker image ls -a
- docker image ls ubuntu
- docker image ls ubuntu:18.04
- docker image ls -f since=mongo:3.2 `since、before`
- docker image ls -f label=com.example.verison=0.1
- docker image ls -q ` # 只查看 image id `
- docker image ls --format "{{.ID}}:{{.Repository}}"
- docker image ls --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}"
docker image rm 386
docker image rm ubuntu
docler image ls --digests
docker image rm node@sha256:b4f0e0bdeb578043c1ea6862f0d40cc4afe32a4a582f3be235a3b164422be228
unstage delete
# 命令搭配使用
docker image rm $(docker image ls -q redis)
docker image rm $(docker image ls -q -f before=mongo:3.2)
docker commit 慎用
docker commit [选项] <容器ID或容器名> [<仓库名>[:<标签>]]
docker run --name webserver -d -p 80:80 nginx
docker exec -it webserver bash # 进入到容器,修改内容
echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
exit
docker diff webserver
docker commit --author "wangzhy@cloud.com" --message "学习使用docker" webserver nginx:v2
docker history nginx:v2
docker run --name web2 -d -p 81:80 nginx:v2
docker save、docker load
$ docker save nginx:v3 -o 文件名称
$ docker save alpine | gzip > alpine-latest.tar.gz
$ docker load -i alpine-latest.tar.gz
如果我们结合这两个命令以及 ssh 甚至 pv 的话,利用 Linux 强大的管道,我们可以写一个命令完成从一个机器将镜像迁移到另一个机器,并且带进度条的功能:
docker save <镜像名> | bzip2 | pv | ssh <用户名>@<主机名> 'cat | docker load'
容器
当利用 docker run 来创建容器时,Docker 在后台运行的标准操作包括:
检查本地是否存在指定的镜像,不存在就从 registry 下载 利用镜像创建并启动一个容器 分配一个文件系统,并在只读的镜像层外面挂载一层可读写层 从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去 从地址池配置一个 ip 地址给容器 执行用户指定的应用程序 执行完毕后容器被终止
docker run ubuntu:18.04 /bin/echo 'Hello world'
docker run -t -i ubuntu:18.04 /bin/bash
docker run ubuntu:18.04 /bin/sh -c "while true; do echo hello world; sleep 1; done"
-d 后台允许
$ docker container ls
$ docker container logs [container ID or NAMES]
$ docker container ls -a
docker container start
docker container restart
docker container run
$ docker run -dit ubuntu
$ docker container ls
$ docker attach 243c
$ docker run -dit ubuntu
$ docker container ls
$ docker exec -i 69d1 bash
$ docker exec -it 69d1 bash
导出
$ docker container ls -a
test
$ docker export 7691a814370e > ubuntu.tar
导入
$ cat ubuntu.tar | docker import - test/ubuntu:v1.0
$ docker image ls
$ docker import http://example.com/exampleimage.tgz example/imagerepo
删除
$ docker container rm trusting_newton
如果要删除一个运行中的容器,可以添加 -f 参数。Docker 会发送 SIGKILL 信号给容器
清理所有处于终止状态的容器
$ docker container prune
二、通过 Dockerfile 构建镜像
- 编写 Dockerfile 文件
- 执行构建镜像命令
docker build -t nginx:v3 .这条命令有个小数点,表示当前目录,这是在指定上下文路径
Dockerfile 文件中包含的是一条条指令(每条指令会构建一层,因此需要注意下简化命令或者使用 && 将命令连接起来)
Dockerfile 的简单示例
FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
FROM 指令 (必须要有,并且是第一条指令)
指定基础镜像,即在哪个镜像上面进行定制。
scratch 是空白镜像。 FROM scratch
MAINTAINER
记录维护者的信息,一般是 name + email 例如 wangzhy<491857242@qq.com>
RUN 指令
RUN 指令是用来执行命令行命令的。由于命令行的强大能力,RUN 指令在定制镜像时是最常用的指令之一
-
RUN <命令> -
RUN ["可执行文件", "参数1", "参数2"]
CMD
- shell 格式:
CMD <命令> - exec 格式:
CMD ["可执行文件", "参数1", "参数2"...] - 参数列表格式:
CMD ["参数1", "参数2"...]。在指定了 ENTRYPOINT 指令后,用 CMD 指定具体的参数。
每个 Dockerfile 只能有一条 CMD 命令。如果指定了多条命令,只有最后一条执行。如果在启动容器的时候指定了运行的命令,则会覆盖掉 CMD 制定的命令。
EXPOSE
暴露端口,使用 -P 会随机绑定 EXPOSE 暴露的端口。
ENV
指定环境变量。
COPY
复制文件到镜像中。
COPY package.json /usr/src/app/
COPY hom* /mydir/
COPY hom?.txt /mydir/
--chown=<user>:<group> 来改变文件的所属用户和用户组
COPY --chown=55:mygroup files* /mydir/
COPY --chown=bin files* /mydir/
COPY --chown=1 files* /mydir/
COPY --chown=10:11 files* /mydir/
ADD
同 COPY 一样,复制文件到镜像中,如果为压缩文件,会自动解压。
ENTRYPOINT
当指定了 ENTRYPOINT 后,CMD 的含义就发生了改变,不再是直接的运行其命令,而是将 CMD 的内容作为参数传给 ENTRYPOINT
指令,换句话说实际执行时,将变为:<ENTRYPOINT> "<CMD>"