我是基于ChatGPT-turbo-3.5实现的AI助手,在此网站上负责整理和概括文章

本文介绍了Docker的可视化管理工具Portainer的安装与使用方法,详细讲解了镜像的生命周期管理、命令操作、构建方法及导出导入技巧。同时,文章涵盖了容器的基本操作、磁盘空间清理以及私有仓库Harbor的部署与维护。这些内容旨在帮助用户高效管理Docker环境,提升操作便捷性和安全性。

# Docker可视化

portainer是Docker图形化界面管理工具!提供一个后台面板供我们操作!

# 运行如下命令即可 打开可视化服务
docker run -d -p 8080:9000 \
--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer

访问:http://ip:8080/

# 镜像管理

# 镜像生命周期管理

graph LR
A[构建] --> B[标记]
B --> C[测试]
C --> D[推送]
D --> E[拉取]
E --> F[运行]
F --> G[清理]

# 镜像操作全命令

命令 说明 示例
docker images 列出本地镜像 docker images --filter "dangling=true"
docker image prune 清理临时镜像 docker image prune
docker search 搜索镜像 docker search --limit 5 nginx
docker pull 拉取镜像 docker pull alpine:3.15
docker tag 标记镜像 docker tag alpine:3.15 myalpine:v1
docker rmi 删除镜像 docker rmi $(docker images -q -f dangling=true)
docker history 查看构建历史 docker history nginx:alpine
docker save 导出镜像 docker save -o nginx.tar nginx:latest
docker load 导入镜像 docker load -i nginx.tar

# 构建镜像

# 通过Dockerfile构建

FROM alpine:3.14
RUN apk add --no-cache nginx && \
    mkdir -p /run/nginx
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

构建命令:

docker build -t my-nginx:1.0 .
# -t: 创建镜像的标签
# . 表示Dockerfile文件在当前路径
# -f 参数指定 Dockerfile 的位置

# 通过容器提交

docker commit <container_id> my-custom-image:1.0

构建一个带有bash和vim的alpine镜像:

docker run -it alpine
echo "https://mirror.tuna.tsinghua.edu.cn/alpine/v3.4/main/" > /etc/apk/repositories
# 安装bash vim
apk update && apk upgrade && apk add --no-cache bash bash-doc bash-completion vim && rm -rf /var/cache/apk/* && /bin/bash
docker commit 4cb9079a8de4 alpine-vim-bash:1.0
sha256:88068208e6f16aba3743a727a7da88659afc2c8315cb3981fda7fe48178b0f5f

# 镜像导出导入

# 导出方式对比

方式 命令组合 保存内容 适用场景 文件大小
镜像打包 save + load 完整镜像(含所有元数据) 镜像的完整迁移 较大
容器快照 export + import 容器文件系统快照 容器状态保存 较小
镜像压缩传输 save + gzip 压缩后的完整镜像 网络传输/长期存储 最小
对比维度 save/load export/import
:----------- :--------------------------- :---------------
操作对象 镜像 容器
保存内容 完整镜像(含所有层和元数据) 容器文件系统快照
历史记录 保留完整构建历史

# 镜像打包:save/load方式(推荐)

# 导出单个镜像(推荐方式)
docker save -o /path/to/save/image.tar [IMAGE_NAME]:[TAG]

# 导出多个镜像
docker save -o multiple-images.tar \
  ubuntu:20.04 \
  nginx:1.21.3-alpine \
  postgres:13.4

# 使用gzip压缩(节省50%+空间)
docker save [IMAGE_NAME]:[TAG] | gzip > image.tar.gz

# 查看导出进度(使用pv工具)
docker save [IMAGE] | pv -s $(docker image inspect [IMAGE] --format='<!--swig0-->') > image.tar
# 常规导入
docker load -i /path/to/image.tar

# 从压缩文件导入
docker load < image.tar.gz

# 导入时显示详细信息
docker load --verbose -i image.tar

# 查看导入进度
pv image.tar | docker load
# 导出示例
docker pull nginx:1.23.1
docker save -o nginx-1.23.1.tar nginx:1.23.1
ls -lh nginx-1.23.1.tar  # 查看文件大小

# 导入验证
docker image rm nginx:1.23.1
docker load -i nginx-1.23.1.tar
docker images | grep nginx

# 容器快照:export/import方式

# 创建测试容器
docker run -d --name export-test ubuntu:20.04 sleep 3600

# 导出容器文件系统
docker export export-test > ubuntu-container.tar

# 带压缩导出
docker export export-test | gzip > ubuntu-container.tar.gz
# 从tar文件创建镜像
cat ubuntu-container.tar | docker import - my-ubuntu:snapshot

# 指定镜像信息
docker import \
  --message "Imported from container" \
  --change "ENV DEBUG=true" \
  ubuntu-container.tar \
  my-ubuntu:custom

# 验证新镜像
docker run -it my-ubuntu:snapshot /bin/bash

# 高级技巧

批量操作脚本

#!/bin/bash
# 批量导出所有镜像
IMAGES=$(docker images --format "<!--swig1-->:<!--swig2-->" | grep -v "<none>")
for image in $IMAGES; do
    filename=$(echo $image | sed 's/[\/:]/-/g').tar
    docker save -o $filename $image
done

# 批量导入镜像
for file in *.tar; do
    docker load -i $file
done

镜像压缩优化

# 使用pigz多线程压缩(需安装pigz)
docker save nginx | pigz -9 > nginx.tar.gz

# 分卷压缩(适合大镜像)
docker save large-image | split -d -b 2G - large-image-part

# 解压合并
cat large-image-part* | docker load

校验镜像完整性

# 生成校验文件
sha256sum image.tar > image.sha256

# 验证文件完整性
sha256sum -c image.sha256

# 检查镜像元数据
tar -xOf image.tar manifest.json | jq

# 使用 Docker 镜像

Docker 运行容器前需要本地存在对应的镜像,如果本地不存在该镜像,Docker 会从镜像仓库下载该镜像。

# 获取镜像

之前提到过,Docker Hub 上有大量的高质量的镜像可以用,这里我们就说一下怎么获取这些镜像。

从 Docker 镜像仓库获取镜像的命令是 docker pull。其命令格式为:

$ docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]

具体的选项可以通过 docker pull --help 命令看到,这里我们说一下镜像名称的格式。

  • Docker 镜像仓库地址:地址的格式一般是 <域名/IP>[:端口号]。默认地址是 Docker Hub(docker.io)。
  • 仓库名:如之前所说,这里的仓库名是两段式名称,即 <用户名>/<软件名>。对于 Docker Hub,如果不给出用户名,则默认为 library,也就是官方镜像。

比如:

$ docker pull ubuntu:18.04
18.04: Pulling from library/ubuntu
92dc2a97ff99: Pull complete
be13a9d27eb8: Pull complete
c8299583700a: Pull complete
Digest: sha256:4bc3ae6596938cb0d9e5ac51a1152ec9dcac2a1c50829c74abd9c4361e321b26
Status: Downloaded newer image for ubuntu:18.04
docker.io/library/ubuntu:18.04

上面的命令中没有给出 Docker 镜像仓库地址,因此将会从 Docker Hub (docker.io)获取镜像。而镜像名称是 ubuntu:18.04,因此将会获取官方镜像 library/ubuntu 仓库中标签为 18.04 的镜像。docker pull 命令的输出结果最后一行给出了镜像的完整名称,即: docker.io/library/ubuntu:18.04

从下载过程中可以看到我们之前提及的分层存储的概念,镜像是由多层存储所构成。下载也是一层层的去下载,并非单一文件。下载过程中给出了每一层的 ID 的前 12 位。并且下载结束后,给出该镜像完整的 sha256 的摘要,以确保下载一致性。

在使用上面命令的时候,你可能会发现,你所看到的层 ID 以及 sha256 的摘要和这里的不一样。这是因为官方镜像是一直在维护的,有任何新的 bug,或者版本更新,都会进行修复再以原来的标签发布,这样可以确保任何使用这个标签的用户可以获得更安全、更稳定的镜像。

如果从 Docker Hub 下载镜像非常缓慢,可以参照配置镜像加速器。

# 运行

有了镜像后,我们就能够以这个镜像为基础启动并运行一个容器。以上面的 ubuntu:18.04 为例,如果我们打算启动里面的 bash 并且进行交互式操作的话,可以执行下面的命令。

$ docker run -it --rm ubuntu:18.04 bash

root@e7009c6ce357:/# cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.1 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.1 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic

docker run 就是运行容器的命令,具体格式我们会在 容器 一节进行详细讲解,我们这里简要的说明一下上面用到的参数。

  • -it:这是两个参数,一个是 -i:交互式操作,一个是 -t 终端。我们这里打算进入 bash 执行一些命令并查看返回结果,因此我们需要交互式终端。
  • --rm:这个参数是说容器退出后随之将其删除。默认情况下,为了排障需求,退出的容器并不会立即删除,除非手动 docker rm。我们这里只是随便执行个命令,看看结果,不需要排障和保留结果,因此使用 --rm 可以避免浪费空间。
  • ubuntu:18.04:这是指用 ubuntu:18.04 镜像为基础来启动容器。
  • bash:放在镜像名后的是 命令,这里我们希望有个交互式 Shell,因此用的是 bash

进入容器后,我们可以在 Shell 下操作,执行任何所需的命令。这里,我们执行了 cat /etc/os-release,这是 Linux 常用的查看当前系统版本的命令,从返回的结果可以看到容器内是 Ubuntu 18.04.1 LTS 系统。

最后我们通过 exit 退出了这个容器。

# 列出镜像

要想列出已经下载下来的镜像,可以使用 docker image ls 命令。

$ docker image ls
REPOSITORY           TAG                 IMAGE ID            CREATED             SIZE
redis                latest              5f515359c7f8        5 days ago          183 MB
nginx                latest              05a60462f8ba        5 days ago          181 MB
mongo                3.2                 fe9198c04d62        5 days ago          342 MB
<none>               <none>              00285df0df87        5 days ago          342 MB
ubuntu               18.04               329ed837d508        3 days ago          63.3MB
ubuntu               bionic              329ed837d508        3 days ago          63.3MB

列表包含了 仓库名标签镜像 ID创建时间 以及 所占用的空间

其中仓库名、标签在之前的基础概念章节已经介绍过了。镜像 ID 则是镜像的唯一标识,一个镜像可以对应多个 标签。因此,在上面的例子中,我们可以看到 ubuntu:18.04ubuntu:bionic 拥有相同的 ID,因为它们对应的是同一个镜像。

# 镜像体积

如果仔细观察,会注意到,这里标识的所占用空间和在 Docker Hub 上看到的镜像大小不同。比如,ubuntu:18.04 镜像大小,在这里是 63.3MB,但是在 Docker Hub 显示的却是 25.47 MB。这是因为 Docker Hub 中显示的体积是压缩后的体积。在镜像下载和上传过程中镜像是保持着压缩状态的,因此 Docker Hub 所显示的大小是网络传输中更关心的流量大小。而 docker image ls 显示的是镜像下载到本地后,展开的大小,准确说,是展开后的各层所占空间的总和,因为镜像到本地后,查看空间的时候,更关心的是本地磁盘空间占用的大小。

另外一个需要注意的问题是,docker image ls 列表中的镜像体积总和并非是所有镜像实际硬盘消耗。由于 Docker 镜像是多层存储结构,并且可以继承、复用,因此不同镜像可能会因为使用相同的基础镜像,从而拥有共同的层。由于 Docker 使用 Union FS,相同的层只需要保存一份即可,因此实际镜像硬盘占用空间很可能要比这个列表镜像大小的总和要小的多。

你可以通过 docker system df 命令来便捷的查看镜像、容器、数据卷所占用的空间。

$ docker system df

TYPE                TOTAL               ACTIVE              SIZE                RECLAIMABLE
Images              24                  0                   1.992GB             1.992GB (100%)
Containers          1                   0                   62.82MB             62.82MB (100%)
Local Volumes       9                   0                   652.2MB             652.2MB (100%)
Build Cache                                                 0B                  0B

# 虚悬镜像

上面的镜像列表中,还可以看到一个特殊的镜像,这个镜像既没有仓库名,也没有标签,均为 <none>。:

<none>               <none>              00285df0df87        5 days ago          342 MB

这个镜像原本是有镜像名和标签的,原来为 mongo:3.2,随着官方镜像维护,发布了新版本后,重新 docker pull mongo:3.2 时,mongo:3.2 这个镜像名被转移到了新下载的镜像身上,而旧的镜像上的这个名称则被取消,从而成为了 <none>。除了 docker pull 可能导致这种情况,docker build 也同样可以导致这种现象。由于新旧镜像同名,旧镜像名称被取消,从而出现仓库名、标签均为 <none> 的镜像。这类无标签镜像也被称为 虚悬镜像(dangling image) ,可以用下面的命令专门显示这类镜像:

$ docker image ls -f dangling=true
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
<none>              <none>              00285df0df87        5 days ago          342 MB

一般来说,虚悬镜像已经失去了存在的价值,是可以随意删除的,可以用下面的命令删除。

$ docker image prune

# 中间层镜像

为了加速镜像构建、重复利用资源,Docker 会利用 中间层镜像。所以在使用一段时间后,可能会看到一些依赖的中间层镜像。默认的 docker image ls 列表中只会显示顶层镜像,如果希望显示包括中间层镜像在内的所有镜像的话,需要加 -a 参数。

$ docker image ls -a

这样会看到很多无标签的镜像,与之前的虚悬镜像不同,这些无标签的镜像很多都是中间层镜像,是其它镜像所依赖的镜像。这些无标签镜像不应该删除,否则会导致上层镜像因为依赖丢失而出错。实际上,这些镜像也没必要删除,因为之前说过,相同的层只会存一遍,而这些镜像是别的镜像的依赖,因此并不会因为它们被列出来而多存了一份,无论如何你也会需要它们。只要删除那些依赖它们的镜像后,这些依赖的中间层镜像也会被连带删除。

# 列出部分镜像

不加任何参数的情况下,docker image ls 会列出所有顶层镜像,但是有时候我们只希望列出部分镜像。docker image ls 有好几个参数可以帮助做到这个事情。

根据仓库名列出镜像

$ docker image ls ubuntu
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              18.04               329ed837d508        3 days ago          63.3MB
ubuntu              bionic              329ed837d508        3 days ago          63.3MB

列出特定的某个镜像,也就是说指定仓库名和标签

$ docker image ls ubuntu:18.04
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              18.04               329ed837d508        3 days ago          63.3MB

除此以外,docker image ls 还支持强大的过滤器参数 --filter,或者简写 -f。之前我们已经看到了使用过滤器来列出虚悬镜像的用法,它还有更多的用法。比如,我们希望看到在 mongo:3.2 之后建立的镜像,可以用下面的命令:

$ docker image ls -f since=mongo:3.2
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
redis               latest              5f515359c7f8        5 days ago          183 MB
nginx               latest              05a60462f8ba        5 days ago          181 MB

想查看某个位置之前的镜像也可以,只需要把 since 换成 before 即可。

此外,如果镜像构建时,定义了 LABEL,还可以通过 LABEL 来过滤。

$ docker image ls -f label=com.example.version=0.1
...

# 以特定格式显示

默认情况下,docker image ls 会输出一个完整的表格,但是我们并非所有时候都会需要这些内容。比如,刚才删除虚悬镜像的时候,我们需要利用 docker image ls 把所有的虚悬镜像的 ID 列出来,然后才可以交给 docker image rm 命令作为参数来删除指定的这些镜像,这个时候就用到了 -q 参数。

$ docker image ls -q
5f515359c7f8
05a60462f8ba
fe9198c04d62
00285df0df87
329ed837d508
329ed837d508

--filter 配合 -q 产生出指定范围的 ID 列表,然后送给另一个 docker 命令作为参数,从而针对这组实体成批的进行某种操作的做法在 Docker 命令行使用过程中非常常见,不仅仅是镜像,将来我们会在各个命令中看到这类搭配以完成很强大的功能。因此每次在文档看到过滤器后,可以多注意一下它们的用法。

另外一些时候,我们可能只是对表格的结构不满意,希望自己组织列;或者不希望有标题,这样方便其它程序解析结果等,这就用到了 Go 的模板语法

比如,下面的命令会直接列出镜像结果,并且只包含镜像ID和仓库名:

$ docker image ls --format "<!--swig3-->: <!--swig4-->"
5f515359c7f8: redis
05a60462f8ba: nginx
fe9198c04d62: mongo
00285df0df87: <none>
329ed837d508: ubuntu
329ed837d508: ubuntu

或者打算以表格等距显示,并且有标题行,和默认一样,不过自己定义列:

$ docker image ls --format "table <!--swig5-->\t<!--swig6-->\t<!--swig7-->"
IMAGE ID            REPOSITORY          TAG
5f515359c7f8        redis               latest
05a60462f8ba        nginx               latest
fe9198c04d62        mongo               3.2
00285df0df87        <none>              <none>
329ed837d508        ubuntu              18.04
329ed837d508        ubuntu              bionic

# 删除本地镜像

如果要删除本地的镜像,可以使用 docker image rm 命令,其格式为:

$ docker image rm [选项] <镜像1> [<镜像2> ...]

# 用 ID、镜像名、摘要删除镜像

其中,<镜像> 可以是 镜像短 ID镜像长 ID镜像名 或者 镜像摘要

比如我们有这么一些镜像:

$ docker image ls
REPOSITORY                  TAG                 IMAGE ID            CREATED             SIZE
centos                      latest              0584b3d2cf6d        3 weeks ago         196.5 MB
redis                       alpine              501ad78535f0        3 weeks ago         21.03 MB
docker                      latest              cf693ec9b5c7        3 weeks ago         105.1 MB
nginx                       latest              e43d811ce2f4        5 weeks ago         181.5 MB

我们可以用镜像的完整 ID,也称为 长 ID,来删除镜像。使用脚本的时候可能会用长 ID,但是人工输入就太累了,所以更多的时候是用 短 ID 来删除镜像。docker image ls 默认列出的就已经是短 ID 了,一般取前3个字符以上,只要足够区分于别的镜像就可以了。

比如这里,如果我们要删除 redis:alpine 镜像,可以执行:

$ docker image rm 501
Untagged: redis:alpine
Untagged: redis@sha256:f1ed3708f538b537eb9c2a7dd50dc90a706f7debd7e1196c9264edeea521a86d
Deleted: sha256:501ad78535f015d88872e13fa87a828425117e3d28075d0c117932b05bf189b7
Deleted: sha256:96167737e29ca8e9d74982ef2a0dda76ed7b430da55e321c071f0dbff8c2899b
Deleted: sha256:32770d1dcf835f192cafd6b9263b7b597a1778a403a109e2cc2ee866f74adf23
Deleted: sha256:127227698ad74a5846ff5153475e03439d96d4b1c7f2a449c7a826ef74a2d2fa
Deleted: sha256:1333ecc582459bac54e1437335c0816bc17634e131ea0cc48daa27d32c75eab3
Deleted: sha256:4fc455b921edf9c4aea207c51ab39b10b06540c8b4825ba57b3feed1668fa7c7

我们也可以用镜像名,也就是 <仓库名>:<标签>,来删除镜像。

$ docker image rm centos
Untagged: centos:latest
Untagged: centos@sha256:b2f9d1c0ff5f87a4743104d099a3d561002ac500db1b9bfa02a783a46e0d366c
Deleted: sha256:0584b3d2cf6d235ee310cf14b54667d889887b838d3f3d3033acd70fc3c48b8a
Deleted: sha256:97ca462ad9eeae25941546209454496e1d66749d53dfa2ee32bf1faabd239d38

当然,更精确的是使用 镜像摘要 删除镜像。

$ docker image ls --digests
REPOSITORY                  TAG                 DIGEST                                                                    IMAGE ID            CREATED             SIZE
node                        slim                sha256:b4f0e0bdeb578043c1ea6862f0d40cc4afe32a4a582f3be235a3b164422be228   6e0c4c8e3913        3 weeks ago         214 MB

$ docker image rm node@sha256:b4f0e0bdeb578043c1ea6862f0d40cc4afe32a4a582f3be235a3b164422be228
Untagged: node@sha256:b4f0e0bdeb578043c1ea6862f0d40cc4afe32a4a582f3be235a3b164422be228

# Untagged 和 Deleted

如果观察上面这几个命令的运行输出信息的话,你会注意到删除行为分为两类,一类是 Untagged,另一类是 Deleted。我们之前介绍过,镜像的唯一标识是其 ID 和摘要,而一个镜像可以有多个标签。

因此当我们使用上面命令删除镜像的时候,实际上是在要求删除某个标签的镜像。所以首先需要做的是将满足我们要求的所有镜像标签都取消,这就是我们看到的 Untagged 的信息。因为一个镜像可以对应多个标签,因此当我们删除了所指定的标签后,可能还有别的标签指向了这个镜像,如果是这种情况,那么 Delete 行为就不会发生。所以并非所有的 docker image rm 都会产生删除镜像的行为,有可能仅仅是取消了某个标签而已。

当该镜像所有的标签都被取消了,该镜像很可能会失去了存在的意义,因此会触发删除行为。镜像是多层存储结构,因此在删除的时候也是从上层向基础层方向依次进行判断删除。镜像的多层结构让镜像复用变得非常容易,因此很有可能某个其它镜像正依赖于当前镜像的某一层。这种情况,依旧不会触发删除该层的行为。直到没有任何层依赖当前层时,才会真实的删除当前层。这就是为什么,有时候会奇怪,为什么明明没有别的标签指向这个镜像,但是它还是存在的原因,也是为什么有时候会发现所删除的层数和自己 docker pull 看到的层数不一样的原因。

除了镜像依赖以外,还需要注意的是容器对镜像的依赖。如果有用这个镜像启动的容器存在(即使容器没有运行),那么同样不可以删除这个镜像。之前讲过,容器是以镜像为基础,再加一层容器存储层,组成这样的多层存储结构去运行的。因此该镜像如果被这个容器所依赖的,那么删除必然会导致故障。如果这些容器是不需要的,应该先将它们删除,然后再来删除镜像。

# 用 docker image ls 命令来配合

像其它可以承接多个实体的命令一样,可以使用 docker image ls -q 来配合使用 docker image rm,这样可以成批的删除希望删除的镜像。我们在“镜像列表”章节介绍过很多过滤镜像列表的方式都可以拿过来使用。

比如,我们需要删除所有仓库名为 redis 的镜像:

$ docker image rm $(docker image ls -q redis)

或者删除所有在 mongo:3.2 之前的镜像:

$ docker image rm $(docker image ls -q -f before=mongo:3.2)

充分利用你的想象力和 Linux 命令行的强大,你可以完成很多非常赞的功能。

# 容器操作

# 容器操作概览

Docker容器操作涵盖创建、启动、停止、进入、删除等一系列关键流程,这些操作对于高效管理和使用容器化应用至关重要。

操作类型 关键命令
创建容器 docker createdocker run
启动容器 docker start
停止容器 docker stopdocker pausedocker unpause
进入容器 docker attachdocker exec
删除容器 docker rm
查看容器 docker inspectdocker topdocker statsdocker logsdocker ps
数据交互 docker cp
其他操作 docker diffdocker portdocker updatedocker link

# 新建容器

使用docker create命令新建容器,新建的容器处于停止状态。

# 新建的容器处于停止状态
[root@node1 docker]# docker create -it alpine-vim-bash:1.0
c5de226c770860f4a10d07e941fbb3080d98cae6eb50d492f54ecac8fb0a1746

# 启动容器

可通过docker start命令启动容器,容器名称可从docker ps -a的输出中获取,既可以使用容器名,也可以使用容器ID。

# 名称通过docker ps -a start 后粘贴names或者id值启动容器
[root@node1 docker]# docker start focused_hopper
[root@node1 docker]# docker start c5de226c77

# 创建并启动容器

docker run命令等价于先执行docker create,然后执行docker start。其基本语法为docker run [OPTIONS] IMAGE [COMMAND] [ARGS...]

# docker run命令,等价于先执行docker create命令,然后执行docker start
# docker run [OPTIONS] IMAGE [COMMAND] [ARGS...]
[root@node1 docker]# docker exec -it c5de226c77 bash
  • 系统镜像的特殊情况:Docker中系统镜像的缺省命令是bash,如果不加-it bash,命令执行后容器会自动退出。这是因为没有衔接输入流,容器本身就会马上结束。添加-it后,docker命令会为容器分配一个伪终端,并接管其stdin/stdout,支持交互操作,此时bash命令不会自动退出。
  • 服务类容器:以daemon的形式运行,对外提供服务,如web server、数据库等。通过-d以后台方式启动这类容器非常合适。若要排查问题,可通过exec -it进入容器。
  • 工具类容器:通常为我们提供一个临时的工作环境,一般以run -it方式运行,执行exit退出终端时,容器同时停止。

# 守护态后台运行

使用-d参数可让容器在后台以守护态运行。

[root@node1 docker]# docker run -d alpine-vim-bash:1.0 /bin/sh -c "while true; do echo hello; sleep 1; done"
# 查看容器输出
[root@node1 docker]# docker logs 96539cb

# 启动容器并指定名称

使用--name参数可在启动容器时指定容器名称。

[root@node1 docker]# docker run -d --name test01 -it alpine-vim-bash:1.0

# 命令参数详解

命令 说明
-d, --detach=false 指定容器运行于前台还是后台,默认为false
-i, --interactive=false 打开STDIN,用于控制台交互
-t, --tty=false 分配tty设备,支持终端登录,默认为false
-u, --user="" 指定容器的用户
-a, --attach=[] 登录容器(必须是以docker run -d启动的容器)
-w, --workdir="" 指定容器的工作目录
-c, --cpu - shares=0 设置容器CPU权重,在CPU共享场景使用
-e, --env=[] 指定环境变量,容器中可使用该环境变量
-m, --memory="" 指定容器的内存上限
-p, --publish - all=false 指定容器暴露的端口
-h, --hostname="" 指定容器的主机名
-v, --volume=[] 给容器挂载存储卷,挂载到容器的某个目录
--volumes - from=[] 给容器挂载其他容器上的卷,挂载到容器的某个目录
--entrypoint="" 覆盖image的入口点
--env - file=[] 指定环境变量文件,文件格式为每行一个环境变量
--expose=[] 指定容器暴露的端口,即修改镜像的暴露端口
--link=[] 指定容器间的关联,使用其他容器的IPenv等信息
--lxc - conf=[] 指定容器的配置文件,只有在指定--exec - driver=lxc时使用
--name="" 指定容器名字,后续可通过名字进行容器管理,links特性需要使用名字
--net="bridge" 容器网络设置:bridge使用docker daemon指定的网桥;host容器使用主机的网络;container:NAME_or_ID使用其他容器的网路,共享IPPORT等网络资源;none容器使用自己的网络(类似--net=bridge),但不进行配置
--restart="no" 指定容器停止后的重启策略,默认容器退出时不重启:on - failure容器故障退出(返回值非零)时重启;always容器退出时总是重启;--rm=false指定容器停止后自动删除容器(不支持以docker run -d启动的容器)

# 停止容器

# 暂停容器

使用docker pause命令可暂停容器,暂停状态的容器不会占用CPU资源。

[root@node1 docker]# docker pause fd18f0
# 查看status
[root@node1 docker]# docker ps
CONTAINER ID   IMAGE                 COMMAND     CREATED              STATUS                   PORTS     NAMES
fd18f06e4a07   alpine-vim-bash:1.0   "/bin/sh"   About a minute ago   Up 19 seconds (Paused)             ecstatic_chandrasekhar

# 取消暂停继续运行容器

使用docker unpause命令可取消容器的暂停状态,使其继续运行。

[root@node1 docker]# docker unpause fd18f0

# 终止容器

使用docker stop命令可正常终止容器,使用docker kill命令可强行终止容器。当容器中的应用终止时,容器也会自动终止。

# docker stop [OPTIONS] CONTAINER [CONTAINER...]
#  先向容器发送SIGTERM信号,等待一段时间(默认10秒)后,再发送SIGKILL信号
docker stop fd18f0

# 使用docker kill可以强行终止容器 当docker容器中的应用终止时,容器也会自动终止
docker kill 容器ID或者容器名

# 停止所有容器

可通过以下命令停止所有容器:

[root@node1 docker]# docker stop $(docker ps -qa)

# 重启容器

# 使用docker start

docker start命令可启动已停止的容器,使其恢复运行。

docker start 容器ID或者容器名

# 使用docker restart

docker restart命令可重启正在运行或已停止的容器,相当于先停止容器,再启动容器。

docker restart 容器ID或者容器名

# 进入容器

# 使用attach命令

docker attach命令可直接进入容器,进入的是启动命令的终端,不会启动新的进程。但当多个窗口同时attach到一个容器时,所有窗口都会同步显示,当某个窗口阻塞时,其他窗口也无法操作。

[root@node1 docker]# docker attach fd18f0

# 使用exec命令

docker exec命令可在容器中打开新的终端,并启动新的进程。

[root@node1 docker]# docker exec -it fd18f0 /bin/bash

一般情况下,如果想直接在终端中查看启动命令的输出,使用attach;其他情况使用exec

选项 作用
--detach, -d 后台运行模式,在后台执行命令相关命令
--detach - keys 覆盖容器后台运行的一些参数信息
--env, -e 设置环境变量
--interactive, -i 展示容器输入信息STDIN
--privileged 为命令提供一些扩展权限
--tty, -t 命令行交互模式
--user, -u 设置用户名(format: <name\|uid>[:<group\|gid>]
--workdir, -w 指定容器内的目录

# 退出容器

# 避免Ctrl + c

使用Ctrl + c会直接卡死容器,不建议使用。

# 使用Ctrl + P + Q

Ctrl + P + Q按钮可正常退出容器,且不关闭容器。

# 使用exit

使用exit命令会使容器停止退出。例如,利用“docker restart”命令重启容器、attach命令进入容器后,重启httpdradosgw,并且使用wget验证是否将radosgw重启成功即可。

# 删除容器

# 使用docker rm删除已终止容器

使用docker rm命令可删除已终止或退出的容器。

[root@node1 docker]# docker rm fd18f0 -f
# 删除所有容器
[root@node1 docker]# docker rm $(docker ps -qa)
docker rm -f $(docker ps -a -q)
docker ps -a -q | xargs docker rm

 `docker container ls -a` 命令可以查看所有已经创建的包括终止状态的容器,如果数量太多要一个个删除可能会很麻烦,用下面的命令可以清理掉所有处于终止状态的容器。

$ docker container prune

# 选项说明

选项 说明
-f 通过SIGKILL信号强制删除一个运行中的容器
-l 移除容器间的网络连接,而非容器本身
-v 删除与容器关联的卷

# 导入和导出容器

# 导出容器

使用docker export命令可将一个已经创建的容器导出到一个文件,无论该容器是否处于运行状态。

[root@node1 docker]# docker run -d --name test01 -it alpine-vim-bash:1.0
[root@node1 docker]# docker export -o test1.tar 9c92b887896a
[root@node1 docker]# docker export 9c92b887896a > test2.tar

# 导入文件成为镜像

使用docker import命令可将导出的文件导入成为镜像。

[root@node1 docker]# docker import test2.tar test:1.0
[root@node1 docker]# docker history test:1.0
IMAGE          CREATED          CREATED BY   SIZE      COMMENT
9fadc36235ff   32 seconds ago                34.1MB    Imported from -

# importload区别

  • import:导入容器快照文件,仅保存当前快照状态,丢弃所有历史记录和元数据信息,导入时可以重新制定标签等元数据信息。
  • load:导入镜像存储文件,镜像存储文件将保存完整记录,体积更大。不能对载入的镜像重命名。

# 应用场景

  • docker export的应用场景:主要用来制作基础镜像,比如从一个ubuntu镜像启动一个容器,然后安装一些软件和进行一些设置后,使用docker export保存为一个基础镜像。然后,把这个镜像分发给其他人使用,比如作为基础的开发环境。
  • docker save的应用场景:如果应用是使用docker - compose.yml编排的多个镜像组合,但要部署的客户服务器不能连外网。这时就可以使用docker save将用到的镜像打个包,然后拷贝到客户服务器上使用docker load载入。

# 查看容器

# 查看容器详情信息

使用docker inspect命令可查看容器的详细信息。

[root@node1 docker]# docker inspect 9c92b887896a

# 查看容器内进程

使用docker top命令可查看容器内运行的进程。

[root@node1 docker]# docker top 9c92b887896a

# 查看统计信息

使用docker stats命令可查看容器的统计信息。

[root@node1 docker]# docker stats 9c92b887896a

# 查看容器日志

使用docker logs命令可查看容器日志。

# docker logs -f -t --tail 容器ID
# -t 是加入时间戳
# -f 跟随最新的日志打印
# --tail 数字 显示最后多少条
# 示例
docker logs -f -t --tail 10 44ca9

# 列出运行的容器

使用docker ps [OPTIONS]命令可列出运行的容器。

  • OPTIONS说明(常用)
    • -a:列出当前所有正在运行的容器 + 历史上运行过的。
    • -l:显示最近创建的容器。
    • -n:显示最近n个创建的容器。
    • -q:静默模式,只显示容器编号。
    • --no - trunc:不截断输出。

# 其他命令

# 复制文件

使用docker cp命令可在容器与宿主机之间复制文件。

# docker cp 容器ID:容器内路径 目的主机路径
[root@node1 docker]# docker cp test1.tar 9c92b887896a:/

# 查看容器文件系统的变更

使用docker diff命令可查看容器文件系统的变更情况。

[root@node1 docker]# docker diff 9c92b887896a

# 查看端口映射

使用docker port命令可查看容器的端口映射情况。

[root@node1 docker]# docker port 9c92b887896a

# 更新容器运行时的配置

使用docker update命令可更新容器运行时的配置,主要用于资源限制。

[root@node1 docker]# docker update --cpu - period 100000 9c92b887896a

# 容器直接互联

通过--link参数可实现容器之间的互联。

# 启动mysql容器
[root@node1 docker]# docker run --name mysqldb -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql:latest
# 启动httpd容器与mysql容器互联
docker run -it --name web --link mysqldb:webdb httpd /bin/bash
# 在 web 容器中就可以使用 webdb 来代替ip来访问mysql了
root@6a1aa3b3d96c:/usr/local/apache2# cat /etc/hosts
127.0.0.1       localhost
::1     localhost ip6 - localhost ip6 - loopback
fe00::0 ip6 - localnet
ff00::0 ip6 - mcastprefix
ff02::1 ip6 - allnodes
ff02::2 ip6 - allrouters
172.17.0.3      webdb 9b938bb01097 mysqldb
172.17.0.4      6a1aa3b3d96c

# Docker仓库

# 命名规则

Docker镜像的完整命名格式为:
[Registry地址/][命名空间/]仓库名[:标签]

# Registry地址

  • 默认地址:Docker Hub(docker.io
  • 私有仓库registry.example.com:5000
  • 云厂商:
    • 阿里云:registry.aliyuncs.com
    • 腾讯云:ccr.ccs.tencentyun.com
  • 省略规则:若未指定Registry,默认使用Docker Hub

# 命名空间

  • 官方镜像:无命名空间(如 nginx
  • 用户镜像用户名/仓库名(如 johndemo/myapp
  • 组织镜像组织名/仓库名(如 google/cloud-sdk

# 仓库名

  • 小写字母、数字、-_. 组成
  • 不能以特殊字符开头或结尾

# 标签(Tag)

  • 默认标签latest
  • 版本标签1.0v2.1.3
  • 系统架构alpinebuster-slim
  • 哈希值sha256:abc123...(精确指向特定镜像层)

# 示例

完整名称 说明
nginx:1.21 Docker Hub官方nginx镜像
johndemo/webapp:prod 用户johndemo的webapp生产镜像
registry.aliyuncs.com/mycompany/api:v3 阿里云私有仓库中的企业镜像

# Docker磁盘空间清理

查看 Docker 的磁盘使用情况:

# 类似于 Linux上的 df 命令
[root@k8s-master01 ~]# docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          15        14        2.575GB   794.5MB (30%)
Containers      38        20        4.687kB   2.391kB (51%)
Local Volumes   2         2         338.6kB   0B (0%)
Build Cache     0         0         0B        0B


TYPE列出了 Docker 使用磁盘的 4 种类型:
Images :所有镜像占用的空间,包括拉取下来的镜像,和本地构建的。
Containers :运行的容器占用的空间,表示每个容器的读写层的空间。
Local Volumes :容器挂载本地数据卷的空间。B
uild Cache :镜像构建过程中产生的缓存空间(只有在使用 BuildKit 时才有,Docker 18.09 以后可用)。
最后的 RECLAIMABLE 是可回收大小。

容器清理

#  仅删除停止运行的容器。
docker container prune
# 删除所有容器(包括停止的、正在运行的)。
docker rm -f $(docker ps -aq) 
docker container rm -f $(docker container ls -aq) 

镜像清理: 有一些镜像是隐形的:

​ 子镜像,就是被其他镜像引用的中间镜像,不能被删除。
​ 悬挂状态的镜像,就是不会再被使用的镜像,可以被删除。

# 通过镜像的id来删除指定镜像。
docker rmi <image id> 
# 除所有镜像。但正在被容器使用的镜像无法删除
docker image rm $(docker image ls -q) 

# 可以列出所有悬挂状态的镜像
docker image ls -f dangling=true
docker image rm $(docker image ls -f dangling=true -q) 
docker image prune

数据卷清理

# 删除不再使用的数据卷
docker volume rm $(docker volume ls -q) 
docker volume prune 

缓存清理: Docker 18.09 引入了 BuildKit ,提升了构建过程的性能、安全、存储管理等能力。

# 删除 build cache。
docker builder prune

一键清理: 注意,这两个命令会把你暂时关闭的容器,以及暂时没有用到的 Docker 镜像都删掉了。

# 可以用于清理磁盘,删除关闭的容器、无用的数据卷和网络,以及 dangling 镜像(即无 tag 的镜像)
docker system prune
# 清理得更加彻底,可以将没有容器使用 Docker镜像都删掉。
docker system prune -a

# 私有仓库Harbor部署

# 最小化生产配置

# harbor.yml 关键配置
hostname: registry.yourcompany.com
http:
  port: 80
https:
  port: 443
  certificate: /etc/ssl/registry.crt
  private_key: /etc/ssl/registry.key
database:
  password: StrongPassword123!
redis:
  password: RedisPass456!
storage:
  filesystem:
    rootdirectory: /data/harbor

# 日常维护命令

# 垃圾回收
docker-compose exec registry registry garbage-collect /etc/registry/config.yml

# 备份恢复
tar czvf harbor-backup-$(date +"%Y%m%d").tar.gz /data/harbor
更新于

请我喝[茶]~( ̄▽ ̄)~*

Fulsun 微信支付

微信支付

Fulsun 支付宝

支付宝