Docker 基础与入门

字数: 12560

根据《docker 技术入门与实践(第 3 版)》进行学习

对命令有疑问,可使用:

1)docker 命令 –help

2)man docker 命令

查看帮助,其中 man docker 命令 里边有详细的解释,包括示例

Docker 安装的目录:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
[root@status volumes]# cd /var/lib/docker/
[root@status docker]# ll
total 36
drwx------  4 root root 4096 Aug 30 13:23 containers		# 容器
drwx------  3 root root 4096 Jul 22 14:58 image				# 镜像
drwxr-x---  3 root root 4096 Jul 22 14:58 network			# 网络
drwx------ 10 root root 4096 Aug 30 13:28 overlay2
drwx------  4 root root 4096 Jul 22 14:58 plugins
drwx------  2 root root 4096 Jul 22 14:58 swarm
drwx------  2 root root 4096 Aug 29 14:52 tmp
drwx------  2 root root 4096 Jul 22 14:58 trust
drwx------  3 root root 4096 Aug 30 16:27 volumes			# 数据卷

Docker 核心概念

三大核心概念:

  • 镜像 image
  • 容器 container
  • 仓库 repository

Docker 大部分的操作都是围绕这三个核心进行

镜像

  • 镜像是创建容器的基础:运行镜像 » 生成容器
  • 镜像本身是只读的。

[!IMPORTANT]

启动镜像生成容器的时候,容器会在镜像的最上层创建一个可写层。 可以把镜像看作一块光盘,里边有黑神话,直接插入光盘,游戏就可以运行,省去不同平台下载安装的麻烦。

容器

容器就是一个盒子,里边打包放了很多东西:操作系统、进程、网络、用户等。

仓库

仓库注册服务器是存放仓库的地方,仓库就是存放镜像的地方,各个镜像文件通过不同的标签进行区分。

仓库有公开仓库和私有仓库

Docker 基础

Docker 镜像

搜索镜像

使用 search 命令在 Docker 仓库中搜索镜像

1
2
3
4
5
docker search 镜像名

# 例子
docker search nginx
docker search centos

获取镜像

1
docker pull 镜像名[:标签]

这里的标签就是这个镜像的版本号,可忽略,不指定的话会默认下载仓库中最新版本(latest)的镜像。一般从稳定性考虑,最好还是输入标签,让各个环境的版本一致。

但是一开始如何知道 pull 了什么版本的镜像呢?

当我们 pull 镜像到本机,可以使用 docker inspect 查看镜像的详细信息。然后里边会有相关的信息版本,比如这里的 nginx_version=1.21.5

1
2
3
4
5
6
 "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "NGINX_VERSION=1.21.5",
                "NJS_VERSION=0.7.1",
                "PKG_RELEASE=1~bullseye"
            ]

然后可以给这个镜像打上版本的 tag

1
docker tag nginx:latest naginx:1.21.5

查看镜像信息

Docker 镜像的信息可以通过相关命令查看

使用 images 命令列出镜像
1
2
3
# 2 种查看命令
docker images
docker image ls

列出本地主机上已有镜像的基本信息

1
2
3
4
5
6
[root@status ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker.io/centos    latest              5d0da3dc9764        2 years ago         231 MB
[root@status ~]# docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker.io/centos    latest              5d0da3dc9764        2 years ago         231 MB

基本信息解释如下:

REPOSITORY - 来源哪个库

TAG - 镜像标签(版本)

IMAGE_ID - 镜像ID

CREATED - 创建时间

SIZE - 镜像大小

使用 tag 命令添加镜像标签

可以使用 docker tag 命令为本地镜像添加新的标签

1
docker tag 镜像名:标签 新镜像名:新标签

相等于这个镜像的别名,因为添加新的标签,它俩的镜像ID是一样的,本质上都是一个镜像。跟 Linux 里的 链接 类似。

这个例子,给 centos:latest 镜像添加新的标签 test:10086

1
2
3
4
5
[root@status ~]# docker tag centos:latest test:10086
[root@status ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker.io/centos    latest              5d0da3dc9764        2 years ago         231 MB
test                10086               5d0da3dc9764        2 years ago         231 MB
使用 inspect 命令查看详细信息

使用 docker inspect 命令获取镜像的详细信息:制作者、适用框架、各层数字摘要等

1
2
docker inspect 镜像名[:标签]
docker inspect 镜像ID
使用 history 命令查看镜像历史

镜像文件由多个层组成,查看各个层的内容具体是什么,使用 history 命令

1
2
3
4
5
[root@status test]# docker history centos
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
5d0da3dc9764        2 years ago         /bin/sh -c #(nop)  CMD ["/bin/bash"]            0 B                 
<missing>           2 years ago         /bin/sh -c #(nop)  LABEL org.label-schema....   0 B                 
<missing>           2 years ago         /bin/sh -c #(nop) ADD file:805cb5e15fb6e0b...   231 MB   

删除镜像

docker rmi 或者 docker image rm 命令可以删除镜像

使用名称+标签删除镜像
1
2
3
4
5
docker rmi 镜像名[:标签]
docker image rm 镜像名[:标签]

docker rmi [options] 镜像名[:标签]
docker image rm [options] 镜像名[:标签]

该命令支持的选项:

  • -force 强制删除镜像,有容器依赖这个镜像,也会删除
  • -no-prune 不要清理未带标签的父镜像
1
docker rmi -force -no-prune 镜像名[:标签]

例子:删除【1.3.2】步骤中的 test:10086 镜像标签

1
2
3
4
5
6
[root@status test]# docker rmi test:10086
Untagged: test:10086
Untagged: docker.io/centos@sha256:a27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177
[root@status test]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker.io/centos    latest              5d0da3dc9764        2 years ago         231 MB

例子:彻底删除镜像,当该镜像没有任何标签的时候,删除镜像,就真的没有了

1
[root@status test]# docker rmi centos:latest
使用镜像ID删除镜像

使用镜像ID进行删除,会将该镜像+它的标签,一起删除

1
docker rmi 镜像ID
  • 镜像已经运行,生成容器了,那这个镜像是无法被删除的。可以通过 -force 强制删除。
1
docker rmi -force 镜像ID
  • 不推荐直接删除镜像的,应该先删除该镜像相关的容器,再删除镜像
1
2
docker rm 容器ID
docker rmi 镜像ID

清理镜像

在 Docker 使用一段时间后,可能会遗留一些临时的镜像文件,以及一些没有使用的镜像,可以通过 docker image prune 命令清理掉。

1
docker image prune

该命令支持的选项:

  • -a 删除所有无用镜像(临时 + 没有被使用的)
  • -f 强制删除
  • -filter 只清理复核给定过滤器的镜像

例子:自动清理临时的镜像文件层

1
2
[root@status test]# docker image prune -f
Total reclaimed space: 0 B

创建镜像

创建镜像的方法:

  • 基于已有容器创建(前提是这个容器的镜像还在)
  • 基于本地模板导入
  • 基于 Dockerfile 创建
基于已有容器创建

使用 docker commit 命令

1
docker commit 容器ID 镜像名[:标签]

支持的选项:

  • -a 作者信息
  • -m 给这个镜像添加备注(可以使用 docker inspect 镜像名[:标签] 查看,具体见【1.3.3】步骤)
  • -p 提交时暂停容器的运行(一般不用的吧?)
例子

1)先启动一个镜像,并到容器里执行一个命令

1
2
3
4
[root@status go]# docker run -it centos:latest /bin/bash
[root@720ef900dddc /]# touch  test
[root@720ef900dddc /]# exit
exit

这个容器ID = 720ef900dddc

这个容器,因为已经在里边进行增删改操作,容器内容与它的镜像内容已经不一样了。这个时候可以基于这个容器进行创建一个新的镜像出来。

2)基于这个容器创建新的镜像

1
2
[root@status go]# docker commit -m "Add a new file" -a "weiqi" 720ef900dddc test:20240829_V1 
sha256:9e0017db11d154d7c08c964a14745afd25a667a7b82b68a8a61381bd7a5de205

详解:

-m 给这个镜像加备注

-a 作者信息

720ef900dddc 容器ID

test:20240829_V1 镜像名:标签

3)查看镜像列表

1
2
3
4
[root@status go]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
test                20240829_V1         9e0017db11d1        50 seconds ago      231 MB
docker.io/centos    latest              5d0da3dc9764        2 years ago         231 MB

这里生成了一个新的镜像 test

可以使用 docker inspect 9e0017db11d1 查看它的详细信息,里边就有作者信息、镜像的备注

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
[root@status go]# docker inspect 9e0017db11d1
[
    {
        "Id": "sha256:9e0017db11d154d7c08c964a14745afd25a667a7b82b68a8a61381bd7a5de205",
        "RepoTags": [
            "test:20240829_V1"
        ],
        "RepoDigests": [],
        "Parent": "sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6",
        "Comment": "Add a new file",
        "Created": "2024-08-29T06:26:49.211537969Z",
        "Container": "720ef900dddc4666e553ed9c26458b6fd4df541fa0939930b4479925d2ca2f0e",
        "ContainerConfig": {
            "Hostname": "720ef900dddc",
            "Domainname": "",
            "User": "",
            "AttachStdin": true,
            "AttachStdout": true,
            "AttachStderr": true,
            "Tty": true,
            "OpenStdin": true,
            "StdinOnce": true,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/bash"
            ],
            "Image": "centos:latest",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {
                "org.label-schema.build-date": "20210915",
                "org.label-schema.license": "GPLv2",
                "org.label-schema.name": "CentOS Base Image",
                "org.label-schema.schema-version": "1.0",
                "org.label-schema.vendor": "CentOS"
            }
        },
        "DockerVersion": "1.13.1",
        "Author": "weiqi",
        "Config": {
            "Hostname": "",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/bash"
            ],
            "Image": "",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {
                "org.label-schema.build-date": "20210915",
                "org.label-schema.license": "GPLv2",
                "org.label-schema.name": "CentOS Base Image",
                "org.label-schema.schema-version": "1.0",
                "org.label-schema.vendor": "CentOS"
            }
        },
        "Architecture": "amd64",
        "Os": "linux",
        "Size": 231268873,
        "VirtualSize": 231268873,
        "GraphDriver": {
            "Name": "overlay2",
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/c36ca0390a29eaefd180fcb6f80d57f127acfa92b9bedbd09a6d84c3a2e6e9f2/diff",
                "MergedDir": "/var/lib/docker/overlay2/8548138b25638a23cdff292a6548e6e8698d59d98afde1866ea91684cfd2600b/merged",
                "UpperDir": "/var/lib/docker/overlay2/8548138b25638a23cdff292a6548e6e8698d59d98afde1866ea91684cfd2600b/diff",
                "WorkDir": "/var/lib/docker/overlay2/8548138b25638a23cdff292a6548e6e8698d59d98afde1866ea91684cfd2600b/work"
            }
        },
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:74ddd0ec08fa43d09f32636ba91a0a3053b02cb4627c35051aff89f853606b59",
                "sha256:b43592c44888d32269515c418d4f4d02b9517cc0642ef2960bbe9c4efbd0924c"
            ]
        }
    }
]
基于本地模板导入镜像

使用 docker import 命令

1
docker import fileName - 镜像名:标签

这个就不试了,没有本地模板

基于 Dockerfile 创建镜像

实际工作中,这个方式最常见

Dockerfile 是一个文件,利用给定的指令描述基于某个父镜像创建新的镜像。它里边相当于描述了创建的过程。

例子

没有例子,先了解,后边再补充

存出和载入镜像

存出和载入镜像如何理解?就是导出和导入的意思。

  • 存出镜像:就是将镜像保存到本地,方便给别的机器使用
  • 载入镜像:在新机器把镜像文件给加载出来使用
存出镜像

使用 docker save 命令

1
2
docker save -o 存出的文件名 镜像名:标签
docker save -o 存出的文件名 镜像ID

-o 就是 output 的意思

例子

1
2
3
4
5
6
[root@status go]# docker save -o centos.tar.gz centos:latest
[root@status go]# docker save -o test.tar.gz 9e0017db11d1
[root@status go]# ll
total 466000
-rw------- 1 root root 238581248 Aug 29 14:50 centos.tar.gz
-rw------- 1 root root 238587904 Aug 29 14:52 test.tar.gz

这两个就是镜像文件了,把这个拿给别人,直接加载使用就可以

载入镜像

使用 docker load 命令

1
2
docker load -i centos.tar.gz
docker load -i test.tar.gz

然后再使用 docker images 查看镜像列表,看看加载成功没,就可以了。

上传镜像

使用 docker push 命令推送镜像到镜像仓库,默认是推送到 Docker Hub 的。

1
docker push 镜像名:标签 | 仓库IP:仓库端口/镜像名:标签
例子

用户 WeiQ 想要推送本地的镜像 centos:latest 到仓库中,怎么推?

先给要推送的镜像添加新的标签,再推送这个标签的镜像,方便区分是 WeiQ 推送的

1
2
docker tag centos:latest WeiQ/centos:latest
docker push WeiQ/centos:latest

运行镜像

使用 docker run 命令,它是运行镜像,生成对应的容器,所以这个命令也可以归为运行容器

与启动容器命令是一样的

Docker 容器

  • 容器,是运行镜像生成的,并且是有可写文件层的
  • 容器,是集合了 应用 + 操作环境 的一个盒子

创建容器

创建容器涉及到

  • create 创建
  • start 启动容器
  • run 创建并启动
  • wait
  • logs
新建容器

创建容器的命令是 docker create ,创建的容器是非运行状态;可通过 docker ps -a 查看新创建的容器

1
docker create -it 镜像名:标签

它支持的选项很多,一般常用就 -it --name -d -p -e

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
--name:为容器指定一个名称。
-it:这是两个选项的组合,-i 允许你通过 STDIN 与容器交互,-t 分配一个伪终端。
-d:以守护态(后台)运行容器。
-p:映射容器的端口到宿主机的端口。
-P:随机映射所有暴露的端口到宿主机的端口。
-v:挂载宿主机的一个卷到容器内。
-e:设置环境变量。
--env-file:从一个文件中读取环境变量。
--network:将容器连接到指定的网络。
--restart:设置容器的重启策略。
--cpus:限制容器可以使用的 CPU 数量。
--memory:限制容器可以使用的内存量。
--memory-swap:限制容器可以使用的内存加上交换空间的总和。
--entrypoint:覆盖镜像的默认入口点。
--cmd:覆盖镜像的默认命令。
--label:设置容器的元数据标签。
--user:指定运行容器的用户。
--workdir:指定容器的工作目录。
--hostname:设置容器的主机名。
--mac-address:设置容器的 MAC 地址。
--ip:设置容器的 IPv4 地址(当使用自定义网络时)。
--add-host:添加自定义的 host-to-IP 映射(host:IP)。
--volume-driver:指定容器的卷驱动。
--stop-signal:设置停止容器的信号。

例子,创建一个别名为 centos7 的容器

1
2
3
4
5
[root@status ~]# docker create --name centos7 -it centos:latest
77c3b94004ddb337d7a1fd66aa4b7a4c45347918a1664020618e82eb1438655a
[root@status ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS                         PORTS               NAMES
77c3b94004dd        centos:latest       "/bin/bash"         2 seconds ago        Created                                            centos7
启动容器

使用 docker start 命令

1
2
docker start 容器名
docker start 容器ID

然后可以使用 docker ps 查看正在运行的容器

1
2
3
4
5
[root@status ~]# docker start centos7
centos7
[root@status ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
77c3b94004dd        centos:latest       "/bin/bash"         23 minutes ago      Up 6 seconds                            centos7
新建并启动容器

使用 docker run 命令

1
2
3
docker run -it 镜像名:标签
docker run -it 镜像ID
docker run -it --name 容器名称 镜像ID

-i 让容器的标准输入保存打开,就是打开容器的执行窗口

-t 让 Docker 分配一个伪终端并绑定到容器的标准输入上

1
2
3
4
5
[root@status ~]# docker run -d --name centos7 -it centos:latest
c0121f9cb884f0783b86c077cb027025cc472515fe2d9267d4073e7000a9bd7c
[root@status ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
c0121f9cb884        centos:latest       "/bin/bash"         30 minutes ago      Up 30 minutes                           centos7
执行 docker run 的原理

执行时,docker 在后台的操作:

1)检查本地是否存在镜像,不存在则从共有仓库拉取

2)利用镜像创建一个容器,并启动容器

3)分配一个文件系统给容器,并在只读的镜像层外挂载一层可读写层

4)从宿主主机配置的网桥接口接一个虚拟接口到容器中

5)从网桥的地址池配置一个 IP 地址给容器

6)执行用户指定的应用程序

exit 退出销毁容器 *

docker run 是会生成容器的,那这里的创建容器是为了什么?因为创建新容器,它里边不就什么都没有?

[!IMPORTANT]

run 命令其实是 create 与 start 命令的合集,它等于创建容器、启动容器

验证:

1)运行镜像,进入容器进行增删改操作

1
2
3
4
5
[root@status ~]# docker run -it centos:latest
[root@b0d385386935 /]# cd /home/
[root@b0d385386935 home]# touch test.txt
[root@b0d385386935 home]# ls
test.txt

2)然后退出容器,看看容器是否存在

1
2
3
4
[root@b0d385386935 home]# exit
exit
[root@status ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

3)不存在容器,重新运行镜像,进入容器,查看刚刚创建的 test.txt 文件

1
2
3
4
[root@status ~]# docker run -it centos:latest
[root@6e198af7152d /]# cd /home/
[root@6e198af7152d home]# ls
[root@6e198af7152d home]# 

已经没有了,且这个容器ID也改变了。

[!IMPORTANT]

结论,运行镜像生成容器,在容器内使用 exit 命令退出的时候,容器也会销毁。重新运行镜像则是会生成一个全新的容器。

20241009:这里其实是退出容器,并且这个容器因为执行完命令了,处于退出的状态,并没有销毁,可使用 docker ps -a 查看它。

退出不销毁容器 *

在容器内部,我退出的时候,不销毁容器,让容器继续运行,应该如何操作?

1)使用 ctrl + p 再使用 ctrl + q

1
2
3
4
5
6
[root@status ~]# docker run -it centos:latest
# ctrl + p
# ctrl + q
[root@status ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
7f64fc558ccb        centos:latest       "/bin/bash"         14 seconds ago      Up 13 seconds                           loving_swanson

2)可以重新进入这个容器

1
2
[root@status ~]# docker exec -it 7f64fc558ccb /bin/bash
[root@7f64fc558ccb /]# 
退出容器 *

如果是退出并销毁容器,使用 exit 命令;

如果是退出但保留容器在后台运行,使用 ctrl + p 再使用 ctrl + q

后台运行容器

让容器在后台运行,使用 -d 选项

1
docker run -d 镜像名:标签
查看容器输出
1
docker logs [选项] 容器ID

选项可以有:

–detail 打印详细信息

-f 持续保持输出

–tail string 输出从某个时间开始的日志

列出容器

使用 docker ps 命令,列出容器列表

[!IMPORTANT]

docker ps 列出当前运行的容器

支持的参数:

-a 列出所有的容器(运行 + 已停止)

-q 只列出容器 ID

-aq 列出所有容器ID

-l 显示最近创建的容器信息

-n 5 显示最后创建的 5 个容器信息

停止容器

有暂停容器、有终止容器,如何理解?

[!IMPORTANT]

可以把容器看作一个应用进程,暂停容器,就是把进程先暂停,后续还可以直接恢复运行状态。

终止容器,就是把这个应用进程给 KILL 掉了,也就是这个容器被彻底关掉了。

  • pause
  • unpause
  • stop
  • prune
暂停容器

使用 docker pause 命令暂停容器的运行(只是暂停运行,非销毁\删除),使用 docker ps 命令还能查到

1
2
docker pause 容器名
docker pause 容器ID
1
2
3
4
5
6
7
8
[root@status ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
c0121f9cb884        centos:latest       "/bin/bash"         30 minutes ago      Up 30 minutes                           centos7
[root@status ~]# docker pause centos7
centos7
[root@status ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                   PORTS               NAMES
c0121f9cb884        centos:latest       "/bin/bash"         32 minutes ago      Up 32 minutes (Paused)                       centos7

停止之后,STUTAS 变为了 Paused

恢复运行

使用 docker unpause 命令恢复容器的运行

1
2
docker unpause 容器名
docker unpause 容器ID
终止容器

使用 docker stop 命令。把容器给 KILL 掉,使用 docker ps 查看不到了。(这个不是删除容器!)

1
2
docker stop 容器名
docker stop 容器ID
1
2
3
4
[root@status ~]# docker stop centos7
centos7
[root@status ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

使用 docker ps -a 还是可以看到这个容器

重启容器

其实就是【2.1.2 启动容器】步骤

1
2
3
4
5
6
docker start 容器名
docker start 容器ID

# 重启
docker restart 容器名
docker restart 容器ID
1
2
3
4
5
[root@status ~]# docker start centos7
centos7
[root@status ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
c0121f9cb884        centos:latest       "/bin/bash"         46 minutes ago      Up 5 seconds                            centos7

进入容器

在【2.1.3 新建并启动容器】步骤中,通过 -d 让容器后台运行

1
docker run --name centos7 -itd centos:latest

容器后台运行,是不会进入到容器内部的

需要进入容器,使用 docker exec 命令

1
2
docker exec -it 容器名 /bin/bash
docker exec -it 容器ID /bin/bash
1
2
[root@status ~]# docker exec -it centos7 /bin/bash
[root@c0121f9cb884 /]#

这里不使用 /bin/bash ,会进不去

删除容器

docker rm 命令是删除容器

docker rmi 命令是删除镜像

注意区别

  • 删除容器,通常是只能删除非运行状态的容器,使用 pause 暂停的容器也删除不了。必须是 docker ps 命令查不到的容器
  • 强行删除,加入 -f 参数,或者先使用 stop 终止容器
1
2
docker rm -f 容器名
docker rm -f 容器ID
1
2
docker stop 容器名&容器ID
docker rm 容器名&容器ID
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
[root@status ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
c0121f9cb884        centos:latest       "/bin/bash"         2 hours ago         Up 2 hours                              centos7
[root@status ~]# docker stop centos7
centos7
[root@status ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@status ~]# docker rm centos7
centos7
[root@status ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@status ~]# 

导入和导出容器

这个就跟 【1.7 存出和载入镜像】类似,将整体容器导出到文件,然后导入到其他机器中,就可以使用了。

导出容器

使用 docker export 命令

1
docker export -o 文件名.tar.gz 容器名或者容器ID
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
[root@status ~]# docker run --name centos7 -itd centos:latest
9fb9bacc6189204e54463401d3e91326a1256a8bec59d4737e600bc76d789d11
[root@status ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
9fb9bacc6189        centos:latest       "/bin/bash"         3 seconds ago       Up 2 seconds                            centos7
8a848522fedf        centos:latest       "/bin/bash"         29 seconds ago      Up 28 seconds                           stupefied_swartz

[root@status ~]# docker export -o container_centos7.tar.gz centos7
[root@status ~]# ll
total 233008
-rw------- 1 root root 238592512 Aug 30 13:24 container_centos7.tar.gz
导入容器

使用 docker import 命令,导入容器,将变为镜像文件

1
docker import 包名 名称:标签
例子
1
2
3
4
5
6
7
[root@status ~]# docker import container_centos7.tar.gz test_import/centos:20240830_V1
sha256:592397d362e5fb6e89f5718e13c19a9f8a74562a7f97c10108aa4b30c9e3c0f2
[root@status ~]# docker images
REPOSITORY           TAG                 IMAGE ID            CREATED             SIZE
test_import/centos   20240830_V1         592397d362e5        7 seconds ago       231 MB
test                 20240829_V1         9e0017db11d1        23 hours ago        231 MB
docker.io/centos     latest              5d0da3dc9764        2 years ago         231 MB

container_centos7.tar.gz 导入,生成一个 test_import/centos 的镜像文件,标签是 20240830_V1

迁移环境有 2 种方式
1 打包镜像

1)打包镜像,【1.6.1 基于已有容器创建】章节,以现在容器创建一个镜像文件

2)将这个镜像文件,放到其他机器里,载入镜像文件,【1.7.2 载入镜像】章节。

2 打包容器

1)打包容器,【2.6.1 导出容器】,生成一个容器文件

2)将这个容器文件,放到其他机器里,导入容器文件,【2.6.2 导入容器】

3 区别

其实没啥区别,除了执行的命令有区别,本质上都是将这个容器打包成文件,然后在其他机器上加载生成新镜像,然后运行这个镜像就可以得到一模一样的容器了。

查看容器

在【1.3 查看镜像信息】章节,可以使用 inspect 查看镜像的详细信息

其实 inspect 还可以查看容器的详细信息

  • 查看镜像信息是 docker inspect
  • 查看容器信息是 docker container inspect
查看容器详情
1
2
3
docker container inspect 容器名\容器ID

docker container [options] inspect 容器名\容器ID

支持的选项:

使用 docker container inspect --help 查看,或者

使用 man docker container inspect 查看

1
[root@status ~]# docker container inspect centos7

会有容器ID、创建时间、路径、状态、镜像、配置等

查看容器内进程
1
2
3
docker container top 容器名\容器ID

docker top 容器名\容器ID

使用 docker container top 方便区分是容器的操作命令

1
2
3
[root@status ~]# docker container top centos7
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                31467               31450               0                   13:23               pts/2               00:00:00            /bin/bash
查看统计信息
1
2
3
docker container stats 容器名\容器ID

docker container stats [options] 容器名\容器ID

支持的选项:

-a 输出所有容器统计信息,不加就是显示运行状态的容器信息

–format string 格式化输出信息

–no-stream 不持续输出,默认是自动更新实时结果的

其他容器命令

  • cp
  • diff
  • port
  • update
复制文件 cp

cp 命令支持在容器与主机之间复制文件

1
docker container cp 主机内容 容器:/容器路径/

也可以从容器传到主机

1
docker container cp 容器:/路径/文件 /主机路径

例子

将本地的 sh 文件复制到 centos7 容器的 tmp 目录下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
[root@status shell]# docker container cp /home/shell/serviceCheckDay.sh centos7:/tmp
[root@status shell]# docker exec -it centos7 /bin/bash
[root@9fb9bacc6189 /]# cd tmp/
[root@9fb9bacc6189 tmp]# ls
ks-script-4luisyla  ks-script-o23i7rc2  ks-script-x6ei4wuu  serviceCheckDay.sh
[root@9fb9bacc6189 tmp]# ls -l
total 16
-rwx------ 1 root root  701 Sep 15  2021 ks-script-4luisyla
-rwx------ 1 root root  671 Sep 15  2021 ks-script-o23i7rc2
-rwx------ 1 root root  291 Sep 15  2021 ks-script-x6ei4wuu
-rwxr-xr-x 1 root root 2467 Jul 23 03:13 serviceCheckDay.sh
查看变更 diff

diff 命令

1
docker container diff 容器名\容器ID
1
2
3
4
5
[root@status shell]# docker container diff centos7
C /run
D /run/secrets
C /tmp
A /tmp/serviceCheckDay.sh

有变更的目录和文件都显示出来

查看端口映射 port

port 命令

1
docker container port 容器名\容器ID
更新配置 update

update 命令

1
docker container update 容器名\容器ID --需要更新的参数

参数:用到再看

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
[root@status shell]# docker container update --help

Usage:  docker container update [OPTIONS] CONTAINER [CONTAINER...]

Update configuration of one or more containers

Options:
      --blkio-weight uint16         Block IO (relative weight), between 10 and 1000, or 0 to disable (default 0)
      --cpu-period int              Limit CPU CFS (Completely Fair Scheduler) period
      --cpu-quota int               Limit CPU CFS (Completely Fair Scheduler) quota
      --cpu-rt-period int           Limit the CPU real-time period in microseconds
      --cpu-rt-runtime int          Limit the CPU real-time runtime in microseconds
  -c, --cpu-shares int              CPU shares (relative weight)
      --cpuset-cpus string          CPUs in which to allow execution (0-3, 0,1)
      --cpuset-mems string          MEMs in which to allow execution (0-3, 0,1)
      --help                        Print usage
      --kernel-memory string        Kernel memory limit
  -m, --memory string               Memory limit
      --memory-reservation string   Memory soft limit
      --memory-swap string          Swap limit equal to memory plus swap: '-1' to enable unlimited swap
      --restart string              Restart policy to apply when a container exits

仓库

官方仓库 Docker Hub ,现在已经被墙了

使用国内的仓库源就可以

具体配置了一个阿里云的镜像仓库,看《Docker 安装与配置》,配置文件为 /etc/docker/daemon.json

搭建本地私有仓库 *

先不看

Docker 进阶

Docker 数据管理

在生成环境种使用 Docker ,特别是数据库放在 Docker 里,或者应用中上传的文件、资料等,需要对数据进行持久化,否则在进行应用版本升级或者容器挂掉后,重新利用镜像生成容器,数据全没了。

之前做某银行的审计内控项目,使用的 Docker 部署应用,每当应用需要修改或者优化的时候,都需要重新上传应用包到某个地方,然后部署。他们应该使用 devops 一键部署的,我上传包到对应的地方,然后执行一个 yaml 命令,每次都是重新生成容器,原先的东西就全没了。

数据管理有 2 种方式:

  • 数据卷 Data Volumns:容器内数据直接映射到本地主机环境
  • 数据卷容器 Data Volume Containers:使用特定容器维护数据卷

如何在容器内创建数据卷?

如何把本地目录或者文件挂到容器内的数据卷?

如何在容器和主机之间共享数据?

如何实现容器数据的备份和恢复?

数据卷

数据卷是将主机的目录映射进容器,类似 linux 的 mount 挂载共享盘。

  • 数据卷,在各个容器之间都可以共享数据
  • 对数据卷内的数据进行修改,容器和本机的数据也会修改。并且容器可以修改数据卷里的内容,本机也可以
  • 数据卷内的数据修改,不会影响到镜像
创建数据卷

使用 docker volume 命令

1
docker volume create -d local 数据卷名称

-d 表示字符串指定卷驱动程序名称(默认为“local”)

例子

1)在本地创建一个 vol_test 数据卷

1
2
[root@status /]# docker volume create -d local vol_test
vol_test

2)可以在 Docker 安装目录下查看数据卷

1
2
3
4
5
[root@status /]# cd /var/lib/docker/volumes
[root@status volumes]# ll
total 28
-rw------- 1 root root 32768 Aug 30 16:27 metadata.db
drwxr-xr-x 3 root root  4096 Aug 30 16:27 vol_test
查看数据卷详细信息

使用 docker volume inspect 命令

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
[root@status /]# docker volume inspect vol_test 
[
    {
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/vol_test/_data",
        "Name": "vol_test",
        "Options": {},
        "Scope": "local"
    }
]
列出所有数据卷

使用 docker volume ls 命令

1
2
3
[root@status /]# docker volume ls
DRIVER              VOLUME NAME
local               vol_test
清理无用数据卷

使用 docker volume prune 命令

1
2
3
4
5
6
7
8
9
[root@status /]# docker volume prune
WARNING! This will remove all volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Deleted Volumes:
vol_test

Total reclaimed space: 0 B
[root@status /]# docker volume ls
DRIVER              VOLUME NAME
删除数据卷

使用 docker volume rm 命令

1
docker volume rm 数据卷名称
1
2
3
4
5
6
7
8
9
[root@status /]# docker volume create -d local data_test
data_test
[root@status /]# docker volume ls
DRIVER              VOLUME NAME
local               data_test
[root@status /]# docker volume rm data_test 
data_test
[root@status /]# docker volume ls
DRIVER              VOLUME NAME
绑定数据卷

创建容器的时候,可以直接将本地的任意路径挂载到容器内作为数据卷,这种形式本质上也是创建一个数据卷,只不过它是在创建容器的时候直接绑定了,所以叫绑定数据卷。

使用 -mount 命令进行绑定,它有 3 种类型的数据卷:

  • volume 普通数据卷,映射到主机 /var/lib/docker/volume 路径下
  • bind 绑定数据卷,映射到主机指定路径下
  • tmpfs 临时数据卷,只存在内存中

例子:

将本地的 /home/go 目录挂载到容器 /opt/web 内,作为容器卷

1
docker run -d -P --name web -v /home/go:/opt/web centos:latest
  • -P 是映射所有端口

这里直接绑定数据卷的容器,使用 docker ps -a 命令查看,它的状态是:Exited

1
2
3
[root@status ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
3577d310d7b1        centos:latest       "/bin/bash"         4 minutes ago       Exited (0) 4 minutes ago                       web

不清楚啥原因,先把它删了:

1
docker rm 3577d310d7b1

再重新创建容器并绑定数据卷,这次在命令后边接执行命令

1
docker run -d -P --name web -v /home/go:/opt/web centos:latest /bin/bash

啊,不行,先跳过,这个不知道为啥

数据卷容器

如果需要在多个容器之间共享一些持续更新的数据,使用数据卷容器是最简单的方式。

数据卷容器也是一个容器,只不过它提供数据卷,给其他容器挂载。

例子

1)创建一个数据卷容器,并在其中创建数据卷挂载到容器里,将本地的 /dbdata 挂载到容器 dbdata 里

1
2
3
4
[root@status ~]# docker run -it -v /dbdata --name dbdata centos:latest
[root@bab3308ef270 /]# ls
bin  dbdata  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@bab3308ef270 /]# [root@status ~]# 

使用 ctrl+pctrl+q 让容器在后台运行

2)在其他容器中使用 --volumes-from 来挂载容器中的数据卷

可以创建新的容器,并挂载这个数据卷容器

1
2
3
[root@status ~]# docker run -it --volumes-from dbdata --name db1 centos:latest
[root@64e8cf50b3be /]# ls
bin  dbdata  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

这里 db1 容器里,已经有了这个 dbdata 数据卷容器了

3)在容器内,往数据卷容器创建新文件,看看数据卷容器是否也被创建

进入数据卷容器,可以看到,是可以同步的

1
2
3
4
[root@status ~]# docker exec -it dbdata /bin/bash
[root@bab3308ef270 /]# cd /dbdata/
[root@bab3308ef270 dbdata]# ls
test.go

4)再创建一个容器并挂载数据卷容器

1
2
3
4
5
6
[root@status ~]# docker run -it --volumes-from dbdata --name db2 centos:latest
[root@0bcca546d72d /]# ls        
bin  dbdata  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@0bcca546d72d /]# cd dbdata/
[root@0bcca546d72d dbdata]# ls
test.go

5)在数据卷容器里操作,其他容器也同时生效,因为里边的数据是共享的

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
[root@status ~]# docker exec -it dbdata /bin/bash
[root@bab3308ef270 /]# ls
bin  dbdata  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@bab3308ef270 /]# cd dbdata/
[root@bab3308ef270 dbdata]# ls
test.go
[root@bab3308ef270 dbdata]# mkdir test1 test2 test3 
[root@bab3308ef270 dbdata]# ls
test.go  test1  test2  test3
[root@bab3308ef270 dbdata]# rm -rf test.go 
[root@bab3308ef270 dbdata]# [root@status ~]# 

[root@status ~]# docker exec -it db2 /bin/bash
[root@0bcca546d72d /]# cd dbdata/
[root@0bcca546d72d dbdata]# ls
test1  test2  test3

[!IMPORTANT]

总结

正常的,数据卷容器只要存在,就可以相当于 NFS 或者 NAS 一样,作为一个挂载盘在容器之间共享。只要这个容器不被销毁。

注意

数据卷容器,本质上是一个容器,只不过它是挂载了数据卷,然后又将这个容器挂载到其他容器中。

  • 使用 docker volume ls 查看的是数据卷
  • 使用 docker ps 查看的是数据卷容器

利用数据卷容器进行数据迁移

因为数据卷容器,它就是个容器,将这个容器导出来,放到其他机器上,可以实现数据的迁移、备份

使用数据卷容器备份数据

理论上是可以的,验证一下看看:

1)导出容器

1
2
3
4
[root@status ~]# docker export -o bak.tar.gz dbdata
[root@status ~]# ll
total 233008
-rw------- 1 root root 238593024 Sep  3 16:13 bak.tar.gz

2)导入容器

1
2
3
4
5
[root@status ~]# docker import bak.tar.gz bak_test:20240903V1
sha256:01b390296306643a0ea36d203a846b306d185069937ab3f618fbb864fc1a47a5
[root@status ~]# docker images
REPOSITORY           TAG                 IMAGE ID            CREATED             SIZE
bak_test             20240903V1          01b390296306        4 minutes ago       231 MB

3)进入容器,看看是否 dbdata 目录是否还有文件?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
[root@status ~]# docker run -d -it bak_test:20240903V1 /bin/bash
17a3da2583a3a37c153b6d34afb19c65f8b9f202377ab04af9e315a2edb1db7b
[root@status ~]# ls
bak.tar.gz
[root@status ~]# docker ps
CONTAINER ID        IMAGE                 COMMAND             CREATED             STATUS              PORTS               NAMES
17a3da2583a3        bak_test:20240903V1   "/bin/bash"         18 seconds ago      Up 17 seconds                           heuristic_jang
[root@status ~]# docker exec -it heuristic_jang /bin/bash
[root@17a3da2583a3 /]# ls
bin  dbdata  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@17a3da2583a3 /]# cd dbdata/
[root@17a3da2583a3 dbdata]# ls
[root@17a3da2583a3 dbdata]# 

dbdata 里边没有数据,很奇怪

4)查看数据卷容器

1
2
3
4
5
6
[root@status ~]# docker exec -it dbdata /bin/bash
[root@bab3308ef270 /]# ls
bin  dbdata  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@bab3308ef270 /]# cd dbdata/
[root@bab3308ef270 dbdata]# ls
test1  test2  test3

数据卷容器的文件还是有的,但是导出的时候好像并没有导出来?

docker 容器是基于镜像生成的,镜像是一个静态的文件系统,它不会自动包含导入时附带的数据卷的。

如果需要导入时包含数据卷里的数据,可以绑定数据卷,将这个 bak.tar.gz 映射到容器内,然后解压它。

结论:

不能使用数据卷容器备份数据

使用数据卷容器备份数据卷

不能使用数据卷容器做备份,但是可以备份它里边的数据卷,使用 docker run 命令

1
docker run --volumes-from 数据卷容器 -v $(pwd):/bakup --name 新容器名 镜像名:标签 执行的命令

例子

1
docker run --volumes-from dbdata -v $(pwd):/bakup --name worker centos:latest tar -cvf /bakup/bakup.tar.gz /dbdata

命令详解:

  • --volumes-from 是让容器 worker 挂载 dbdata 数据卷容器
  • -v $(pwd):/bakup 是将当前目录,都映射到 worker 容器里的 /bakup 目录
  • tar 命令,就是运行容器之后,立马执行的命令
注意

这个命令生成的容器,因为 tar 命令是前台命令,命令执行完成后,容器会停止。如果需要在后台继续运行该容器,则可以这样

1
docker run -it --volumes-from dbdata -v $(pwd):/bakup --name worker centos:latest /bin/bash -c "tar -cvf /bakup/bakup.tar.gz /dbdata"
使用数据卷容器恢复数据 *

这个百度或者问问 AI

涉及到数据备份和恢复的,都是挺重要的章节,看看怎么单独实践一张。

端口映射、容器互联

生产上,通常各个容器会互相协作,特别是微服务架构的应用,每个服务一个容器。还有数据库与应用之间的互联,应用需要访问到数据库的端口。

  • 映射容器内应用的服务端口到本地主机
  • 互联机制实现多个容器间通过容器名来快速访问

容器的端口映射

如果在启动容器的时候,没有指定对应的端口参数,容器外部是无法通过网络访问容器内的应用服务的。

通过 -p 或者 -P 参数进行端口映射

  • -p 可以指定具体的端口
  • -P 是随机映射一个 49000 ~ 49900 的端口

首先,要知道,容器一旦运行起来是不能修改其端口映射的,必须重新运行一个容器并在启动时就进行映射。

1
dokcer run -d --name 容器名 -p 外部映射端口:容器应用端口 镜像名:标签
从外部访问容器应用

1)启动 nginx 容器,并进行端口映射

1
2
3
4
5
[root@status ~]# docker run -d --name nginx -p 8088:80 nginx:1.21.5
1bb6ac4fee9793393c1fa9066f61105201a5f94e3cb5bc1fb4fe463f96bbe647
[root@status ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
1bb6ac4fee97        nginx:1.21.5        "/docker-entrypoin..."   6 seconds ago       Up 5 seconds        0.0.0.0:8088->80/tcp   nginx

可以看到 0.0.0.0:8088 -> 80/tcp ,说明外部的 8088 端口映射到了容器内部的 80 端口,这个时候,在外部就可以使用 8088 端口访问到容器内部的 80 端口了

2)通过宿主机 IP:PORT 的形式访问 nginx

因为使用的阿里云服务器,所以使用阿里云服务器的 IP:8088 去访问 nginx,前提是阿里云服务器上开通 8088 端口

把 阿里云的安全组的访问规则开通一下 8088 端口,然后就可以访问了

3)查看 docker nginx 日志

1
2
3
4
5
[root@status ~]# docker logs nginx
......
140.207.163.4 - - [06/Sep/2024:02:31:56 +0000] "GET / HTTP/1.1" 200 615 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 Edg/128.0.0.0" "-"
2024/09/06 02:31:56 [error] 30#30: *1 open() "/usr/share/nginx/html/favicon.ico" failed (2: No such file or directory), client: 140.207.163.4, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "139.196.97.87:8088", referrer: "http://139.196.97.87:8088/"
140.207.163.4 - - [06/Sep/2024:02:31:56 +0000] "GET /favicon.ico HTTP/1.1" 404 555 "http://139.196.97.87:8088/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 Edg/128.0.0.0" "-"

可以看到里边记录着谁访问了这个地址

映射所有接口地址

使用 -p port:容器port 的形式,就是默认映射所有地址的,就上边【2.1.1】步骤,这个就是所有地址都可以访问到 8088 端口

1
dokcer run -d --name 容器名 -p 外部映射端口:容器应用端口 镜像名:标签
映射到指定地址的指定端口

使用 -p 指定地址:指定端口:容器端口 可以指定映射的地址和端口

1
docker run -d --name 容器名 -p 指定外部地址:指定外部映射端口:容器应用端口 镜像名:标签
映射到指定地址的任意端口

使用 -p 指定地址::容器端口 可以映射到指定地址的所有端口

1
docker run -d --name 容器名 -p 指定外部地址::容器应用端口 镜像名:标签
查看映射端口的配置

使用 docker port 容器名 命令查看容器当前映射的端口配置

1
2
[root@status ~]# docker port nginx
80/tcp -> 0.0.0.0:8088

查看容器的 IP

可以使用 docker container inspect 查看容器的详细信息,包含 IP

1
docker container inspect 容器名

容器互联

容器互联,可以让多个容器之间的应用进行互相访问,最常见的就是应用容器得访问到数据库容器,应用才能正常运行。

容器的互相连接,采用容器名的方式连接

  • 使用 --link 参数,可以让容器互联

[!CAUTION]

AI回答:

–link 是旧版 docker 的用法,新版(docker 1.9)已经不推荐使用了,因为它需要停止容器后,重新 run 容器才能设置互联。

新版使用 network (docker 的网络功能)连接容器,创建一个网络,然后将需要互联的容器都放到同一个网络中,就可以实现容器互联。

所以,更推荐 network 用法

network 用法

模板

1
docker network 命令选项 网络名
  • create 创建
  • connection 将容器连接到网络
  • disconnection 将容器从网络中移除
  • inspect 展示网络的详细信息
  • ls 展示网络列表
  • prune 删除所有不在使用的网络
  • rm 删除网络
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 1.创建
docker network create 网络名称
# 2.将容器加入网络中
docker network connect 网络名称 <容器1的ID或名字>
docker network connect 网络名称 <容器2的ID或名字>
# 3.将容器从网络中移除
docker network disconnect 网络名称 <容器1的ID或名字>
# 4.展示网络详细信息
docker network inspect 网络名称
# 5.网络列表
docker network ls
# 6.删除所有不在使用的网络
docker network prune
# 7.删除网络
docker network rm 网络名称
例子

将现有的 nginx 容器与 tomcat 容器进行互联(这里使用 network 进行容器互联)

1)启动一个 tomcat 容器,不设置映射端口(一般通过 nginx 进行访问 tomcat,所以有 nginx 能在外部访问到就行)

1
2
[root@status ~]# docker run -d --name tomcat tomcat:10.0.14 
59c519066587ee0ad708f99b91a8d04f0a66c2e087a9327dfdf003832140503c

2)创建一个 docker 网络

1
2
3
4
5
6
7
8
[root@status ~]# docker network create web_network
5b1463443f2a443e2f7fa8277ac96eafcc0c9f0866302b910ce507394d667714
[root@status ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
833b114c72d5        bridge              bridge              local
ea34ff8ed89e        host                host                local
c142124b84e6        none                null                local
5b1463443f2a        web_network         bridge              local

3)将 tomcat 容器和 nginx 容器都拉进来

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
[root@status ~]# docker network connect web_network tomcat
[root@status ~]# docker network connect web_network nginx
[root@status ~]# docker network inspect web_network 
[
    {
        "Name": "web_network",
        "Id": "5b1463443f2a443e2f7fa8277ac96eafcc0c9f0866302b910ce507394d667714",
        "Created": "2024-09-06T11:21:49.319643032+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Containers": {
            "1bb6ac4fee9793393c1fa9066f61105201a5f94e3cb5bc1fb4fe463f96bbe647": {
                "Name": "nginx",
                "EndpointID": "405bee2c3142c87ac6e9d007e021dd4ea4a95e9191ae72dd394343e7fead50e3",
                "MacAddress": "02:42:ac:12:00:03",
                "IPv4Address": "172.18.0.3/16",
                "IPv6Address": ""
            },
            "59c519066587ee0ad708f99b91a8d04f0a66c2e087a9327dfdf003832140503c": {
                "Name": "tomcat",
                "EndpointID": "2296bfc0dbf18154fac66e0100b770cf342b2e8556cde98432bc694839b06ba9",
                "MacAddress": "02:42:ac:12:00:02",
                "IPv4Address": "172.18.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

Dockerfile 构建镜像

Dockerfile 里各个指令填写的文件目录,一般是上下文路径,不需要加路径。只有放入镜像内部的路径才填写绝对路径。

Dockerfile 是一个文件,主要内容:

  • 基础镜像信息 FROM
  • 维护者信息 LABEL
  • 镜像操作指令 RUN
  • 容器启动时执行指令 CMD
  • 设置容器的环境变量 ENV

使用 FROM 指令指明基于哪个基础镜像创建

使用 LABEL 指令说明作者信息

使用 RUN 指令在镜像中执行命令

使用 CMD 指令来指定容器启动的时候执行哪些命令

Dockerfile 主要指令

Dockerfile 指令 说明
FROM 指定基础镜像,用于后续的指令构建。
MAINTAINER 指定Dockerfile的作者/维护者。(已弃用,推荐使用LABEL指令)
LABEL 添加镜像的元数据,使用键值对的形式。
RUN 在构建过程中在镜像中执行命令。
CMD 指定容器创建时的默认命令。(可以被覆盖)
ENTRYPOINT 设置容器创建时的主要命令。(不可被覆盖)
EXPOSE 声明容器运行时监听的特定网络端口。
ENV 在容器内部设置环境变量。
ADD 将文件、目录或远程URL复制到镜像中。
COPY 将文件或目录复制到镜像中。
VOLUME 为容器创建挂载点或声明卷。
WORKDIR 设置后续指令的工作目录。
USER 指定后续指令的用户上下文。
ARG 定义在构建过程中传递给构建器的变量,可使用 “docker build” 命令设置。
ONBUILD 当该镜像被用作另一个构建过程的基础时,添加触发器。
STOPSIGNAL 设置发送给容器以退出的系统调用信号。
HEALTHCHECK 定义周期性检查容器健康状态的命令。
SHELL 覆盖Docker中默认的shell,用于RUN、CMD和ENTRYPOINT指令。

配置指令

FROM

Dockerfile中第一条指令必须是 FROM 指令

1
FROM 镜像名[:标签] [AS 别名]

为了保证镜像精简,可以使用包小的镜像,比如 Alpine \ Debian 作为基础镜像

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
好像是可以有几个 FROM 的?
FROM 
RUN 
...
FROM 
RUN 
....
FROM 
RUN 
..。
LABEL

LABEL指令是给镜像添加元数据标签信息的,包含镜像的基本信息,键值对的形式。可以有多个 LABEL

1
2
3
4
LABEL 键1=值1
LABEL 键2=值2
LABEL 键3=值3
...
1
2
3
4
LABEL version="V1.0"
LABEL author="Weii"
LABEL description="这里一个例子\
      可以换行"
EXPOSE

声明镜像内服务监听的端口。仅仅是声明,不会自动完成端口映射,映射还得是启动容器时的 -p 参数【2.1】步骤。

1
EXPOSE 端口
ENV

指定镜像的环境变量,环境变量在启动容器时也会存在。键值对的形式,也可以有多个 ENV。

1
2
3
4
ENV 键1=值1
ENV 键2=值2
ENV 键3=值3
...
1
2
3
4
ENV JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.272.b10-7.ky10.aarch64
ENV JRE_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.272.b10-7.ky10.aarch64/jre
ENV CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib
ENV PATH=$JAVA_HOME/bin:$PATH
VOLUME

数据卷,给镜像创建一个数据卷挂载点

1
VOLUME ["/path"]

可以在 Dockerfile 直接用 VOLUME 创建,也可以不用。到时候启动容器的时候使用参数挂载数据卷。

USER

指定运行容器时的用户名(指服务器用户名)

1
USER 用户名
WORKDIR

配置容器的主工作目录,给后续的 RUN \ CMD 等指令配置工作目录,RUN \ CMD 执行的命令,就是在这个目录下执行的

1
WORKDIR /path/to/dir
SHELL

指定使用 shell 时的默认 shell 类型

操作指令

RUN

运行指令

1
2
3
4
5
6
7
RUN 命令1
RUN 命令2
RUN 命令3
RUN 命令4 && 命令5 && 命令6
RUN 命令7 \
    && 命令8 \
    && 命令9

注意:

  • 每条 RUN 指令都会生成一层镜像层,都是在上一层的基础上生成新的一层。
  • 可以使用 \ 来换行
  • 合理的利用 RUN 分层,可以提供构建效率
CMD

指定启动容器时执行的命令

1
CMD 命令

注意:

  • 每个 Dockerfile 只能有一条 CMD 指令,如果有多条,则会被最后一条覆盖,只有最后一条会执行。
  • 如果启动容器时指定了执行参数,则会覆盖掉 CMD 指令

docker run -d –name 容器名 镜像名:标签 执行的命令

这里执行的命令,会覆盖掉 Dockerfile 里的 CMD 指令

ADD

添加内容到镜像,一般填写镜像里的绝对路径;

复制的路径,则是 dockerfile 所在的目录,所有包都需要在同一个目录,不能加路径。

1
ADD 需要复制的路径 容器里的绝对路径

比如:复制当前目录内容到容器内的 /home 目录

1
ADD . /home

比如

1
2
ADD jdk.tar.gz /home/install
ADD apache-tomcat-10.1.30.tar.gz /home/install

它会直接解压这个 tar 包到 /home/install 里,所以 RUN 命令不用跟着 tar -xzvf 命令了。

COPY

复制内容到镜像,跟 ADD 差不多,用 ADD。

创建镜像

在编写完 Dockerfile 后,使用 docker image build 命令创建镜像

1
docker image build -t 镜像名称:标签 Dockerfile的路径

该命令的逐条执行 Dockerfile 里的 RUN 指令,如果 RUN 指令过多,会导致创建镜像缓慢。因为每一条 RUN 指令,都会生成一层新镜像,最后才合并到一起。

同样的,docker image build 支持很多选项,具体可需要时百度

选择父镜像

生成新的镜像都是基于 DockerfileFROM 指令中指定的父镜像,父镜像是生成镜像的基础,会影响到生成镜像的大小和功能。

使用 .dockerignore 文件

不看

多步骤创建

总结

[!IMPORTANT]

docker 主要是4个大部分的命令:

  • 镜像命令
  • 容器命令
  • 数据卷命令
  • 网络命令

inspect 都是查看详细信息

ls 都是列出列表

Licensed under CC BY-NC-SA 4.0
最后更新于 2024年10月14号 22:37