根据《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
|
获取镜像
这里的标签就是这个镜像的版本号,可忽略,不指定的话会默认下载仓库中最新版本(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进行删除,会将该镜像+它的标签,一起删除
- 镜像已经运行,生成容器了,那这个镜像是无法被删除的。可以通过
-force
强制删除。
- 不推荐直接删除镜像的,应该先删除该镜像相关的容器,再删除镜像
1
2
|
docker rm 容器ID
docker rmi 镜像ID
|
清理镜像
在 Docker 使用一段时间后,可能会遗留一些临时的镜像文件,以及一些没有使用的镜像,可以通过 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
选项
查看容器输出
选项可以有:
–detail 打印详细信息
-f 持续保持输出
–tail string 输出从某个时间开始的日志
列出容器
使用 docker ps
命令,列出容器列表
[!IMPORTANT]
docker ps 列出当前运行的容器
支持的参数:
-a 列出所有的容器(运行 + 已停止)
-q 只列出容器 ID
-aq 列出所有容器ID
-l 显示最近创建的容器信息
-n 5 显示最后创建的 5 个容器信息
停止容器
有暂停容器、有终止容器,如何理解?
[!IMPORTANT]
可以把容器看作一个应用进程,暂停容器,就是把进程先暂停,后续还可以直接恢复运行状态。
终止容器,就是把这个应用进程给 KILL 掉了,也就是这个容器被彻底关掉了。
暂停容器
使用 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
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
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
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
|
这里直接绑定数据卷的容器,使用 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 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+p
再 ctrl+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 容器名
|
容器互联
容器互联,可以让多个容器之间的应用进行互相访问,最常见的就是应用容器得访问到数据库容器,应用才能正常运行。
容器的互相连接,采用容器名的方式连接
[!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
指令
为了保证镜像精简,可以使用包小的镜像,比如 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】步骤。
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
数据卷,给镜像创建一个数据卷挂载点
可以在 Dockerfile 直接用 VOLUME 创建,也可以不用。到时候启动容器的时候使用参数挂载数据卷。
USER
指定运行容器时的用户名(指服务器用户名)
WORKDIR
配置容器的主工作目录,给后续的 RUN \ CMD 等指令配置工作目录,RUN \ CMD 执行的命令,就是在这个目录下执行的
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
指定启动容器时执行的命令
注意:
- 每个 Dockerfile 只能有一条 CMD 指令,如果有多条,则会被最后一条覆盖,只有最后一条会执行。
- 如果启动容器时指定了执行参数,则会覆盖掉 CMD 指令
docker run -d –name 容器名 镜像名:标签 执行的命令
这里执行的命令,会覆盖掉 Dockerfile 里的 CMD 指令
ADD
添加内容到镜像,一般填写镜像里的绝对路径;
复制的路径,则是 dockerfile 所在的目录,所有包都需要在同一个目录,不能加路径。
比如:复制当前目录内容到容器内的 /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
支持很多选项,具体可需要时百度
选择父镜像
生成新的镜像都是基于 Dockerfile
的 FROM
指令中指定的父镜像,父镜像是生成镜像的基础,会影响到生成镜像的大小和功能。
使用 .dockerignore 文件
不看
多步骤创建
总结
[!IMPORTANT]
docker 主要是4个大部分的命令:
inspect 都是查看详细信息
ls 都是列出列表