仅为个人查阅使用,要学习 Docker 的话,推荐看这份文档:《Docker — 从入门到实践》
一、基本概念
要构建并运行一个 Docker 容器,有这样几个步骤:
- 编写 Dockerfile,然后通过 build 命令从 Dockerfile 构建镜像
- 镜像是分层构建,分层存储。这使得镜像的复用、定制变的更为容易。
- 镜像不包含任何动态数据,其内容在构建之后就不会被改变。因此它对运维很友好,可以实现一次 build 到处运行。
- 通过 run 命令启动该容器。(镜像仓库后面再记)
- 镜像内容是静态的,而容器是动态的!
- 每一个容器运行时,是以镜像为基础层,在其上创建一个当前容器的存储层。可以称这个为容器运行时读写而准备的存储层为 容器存储层。
- 容器不应该向其存储层内写入任何数据,容器存储层要保持无状态化。
- 所有的文件写入操作,都应该使用 数据卷(Volume)、或者绑定宿主目录,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。
- 用 login 命令登录到 Docker 的镜像仓库(私人的或者公共的),然后通过 push 命令将构建好的镜像推送上去。
- 在别的机器上 pull 镜像下来,通过
docker run xxx
命令运行。
二、Docker 基础命令
1. 获取镜像
通过 pull 命令从仓库中获取镜像:
# 格式
docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]
# e.g. 1:从公共仓库拉 nginx 的镜像
# 下列两条命令效果相同,默认从 library (官方镜像)找镜像,tag 默认为 latest(最新版本)
docker pull library/nginx:latest
docker pull nginx
# e.g. 2:从公共仓库中,拉取个人上传的镜像
docker pull <username>/myblog:latest
# e.g. 3:从私人仓库拉取 ryan 项目下,名为 myblog 的镜像
docker login reg.myharbor.com:4321 # 私人仓库一般都需要先登录,会将登录信息保存到本地
docker pull reg.myharbor.com:4321/ryan/myblog
自己编写 Dockerfile,然后通过 Dockerfile 构建镜像(Dockerfile 的语法后面再细说):
# --tag 可以缩写成 -t,用于指定镜像的 [镜像名:<tag>],其中 <tag> 可省略。
docker build --tag friendlyhello . # 使用当前目录下的 Dockerfile 构建镜像,并且`镜像名:tag`为 `friendlyhello:latest`
2. 查看/删除镜像
查看镜像列表:
docker image ls -a # 列出当前机器上的所有镜像
docker images -a # 上一条命令的缩写
docker images -a <image name> # 查找名为 <image name> 的镜像
删除镜像:
docker image rm <image id>
docker image rm <image name>:<tag> # 删除 <image name> 镜像的一个 tag
docker rmi <xxx> # `docker image rm <xxx>` 的缩写
docker image ls -f dangling=true # 列出所有虚悬镜像(即仓库名和 tag 都为 none 的镜像)
docker image prune # 清除所有未被使用的虚悬镜像(被依赖了的虚悬镜像无法直接清除,见后)
docker image rm $(docker image ls -a -q) # 删除本机的所有镜像(危险操作)
如果一个正常的镜像,或者某个容器依赖了某些虚悬镜像,那这些虚悬镜像就不能被直接删除。你需要先删除掉那个上层的镜像或者容器。
删除该上层镜像时,所有只被它依赖了的虚悬镜像也会被自动清除掉。但是删除上层容器后,还需要手动用 docker image prun
清除被它使用了的虚悬镜像。
3. 启动容器
docker run
: 从指定镜像新建一个容器并运行命令,然后终止运行。标准流程如下:- 检查本地是否存在指定的镜像,不存在就从公有仓库下载
- 利用镜像创建并启动一个容器
- 分配一个文件系统,并在只读的镜像层外面挂载一层可读写层
- 从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去
- 从地址池配置一个 ip 地址给容器
- 执行用户指定的应用程序
- 执行完毕后容器被终止
# 在 ubuntu 18.04 中输出 Hello World
# --rm 表示,容器终止运行后,自动删除该容器
docker run --rm ubuntu:18.04 /bin/echo 'Hello world'
# 进入容器的 bash 终端
# -i 使容器的 stdin 保持打开,-t 为容器分配一个伪 tty。
# 结合使用上述两个选项 `-it`,效果类似 ssh 远程连接。
docker run -it ubuntu:18.04 /bin/bash
# P.S. 其实只需要 -i 参数,就能和容器进行交互了,敲命令能得到回复。
# -t 添加的伪终端,感觉只是在每个命令行开头加了个 `root@25d5c233769b:/# ` 这样的提示符。
docker run -d
:使新建的容器在后台运行
# 在后台启动一个 nginx 容器,提供静态网站访问功能,或者做代理
# -d 表示在后台运行该容器,--rm 使容器在终止后被自动删除
docker run -d --rm my-nginx:latest
# --restart=always 容器意外退出时,总是自动重启。以保证服务总是可用。
# --name my-blog 为容器取个有意义的名字,可在任何命令中,用该名字替换 container id 使用
docker run --rm -d -restart=always --name my-blog my-nginx:latest
# 前台运行的容器,stdout 会被定向到本机的 stdout,所以能直接看到命令的输出
# 而后台运行的容器,就需要通过下面的命令查看输出了
docker logs <container id / container name> # 查看指定容器的 logs,更详细的参数请 man
docker logs -f <container id / container name> # 持续地输出容器的日志(ctrl-c 退出)
- 查看容器列表、启动/终止容器、删除容器
docker container ls -a # 列出所有容器
docker ps -a # 上一条命令的缩写
docker container start <container id / container name> # 启动一个已经终止运行的容器
docker container stop <container id / container name> # 终止一个正在运行的容器(该容器可能在后台工作,也可能是正被别的 shell 运行)
docker container rm <container id / container name> # 删除一个未运行的容器
docker container rm -f <container id / container name> # 强制删除容器,即使该容器正在运行
docker container prune # 清理掉所有已终止的容器
docker [start|stop|rm] <xxx> # 上述命令的缩写,container 可省略
- 登入容器:
# 1. 使用 attach 命令登入(不推荐!!)
# 将容器的 stdin/stdout/stderr 与当前终端接驳,容器切换到前台运行。
# 特别注意的是,因为容器切换到了前台运行,退出会导致容器终止!因此才不推荐用此命令。
docker container attach <container id / container name>` # 可缩写成 `docker attach xxx`
# 2. 使用 exec 命令登入(推荐方式)
4. 镜像/容器的导入和导出
4.1 镜像的导入导出
镜像可以通过中心仓库进行分享,但是有些情况下,我们只想快速地将镜像分享给某台机器。这就需要用到镜像的导入导出功能了:
# a. 将指定镜像导出为 tar 文件
# 注意:如果同名则会覆盖(没有警告)
docker save <imagename>:<tag> -o <filename>
# 使用 gzip 进一步压缩
docker save <imagename>:<tag> | gzip > <imagename>-<tag>.tar.gz
# b. 从指定文件加载镜像
docker load -i <imagename>-<tag>.tar.gz # 不需要先解压
上述导入导出命令,结合 ssh,就能完成镜像的快速分享:
docker save <镜像名> | bzip2 | pv | ssh <用户名>@<主机名> 'cat | docker load'
# pv:即 Pipe Viewer,意思是通过管道显示数据处理进度的信息。一般需要自行安装。
# yay -S pv 或 sudo apt-get install pv 或 yum install pv
4.2 容器的导入和导出
虽然说容器层不应该保存任何动态数据,
但是总有特殊情况(或者说太菜),我们把一些必需的东西放进了容器层,现在要使容器能在另一台机器上运作。
或者容器运行出了问题,我们需要将它导出来分析问题的原因。
这时候,就需要做容器的导入导出了:
# 将容器的当前快照导出为文件
docker export [container id / container name] > ubuntu.tar
# 从文件将容器快照导入为镜像
# 注意!!!是导入成了镜像!并且为这个镜像指定了 [name:tag]
cat ubuntu.tar | docker import - test/ubuntu:v1.0