Docker教程

Docker 的出现,改变了以前传统开发部署运帷的繁琐步骤。作为新时代的开发者,必须掌握这门技术。课程来源:bilibili 遇见狂神说

Docker 概述

Docker 为什么出现?

  • 开发运维环境不同,换设备就不能运行
  • 希望项目能带上环境一起打包
  • 更方便的配置集群
  • 开发步骤
    • 传统:开发 jar,运维来做
    • 现在:开发、打包、部署、上线
  • Docker 给出了解决方案

  • 类似于集装箱
  • Docker 通过隔离机制将服务器利用到极致
  • 本质:需求驱动技术

Docker 历史

  • 2010 年,几个年轻人成立一家公司 dotCloud,做一些云计算业务,有容器技术
  • 经验遇到困难之后,2013 年将 Docker 开源
  • 2014 年 4 月 9 日,Docker1.0 发布
1
2
vm: 需要下载 linux 镜像,体积大,配置要求高,启动慢,笨重;
docker: 隔离,寄生于宿主机,配置要求低,启动快,小巧。

DevOps(开发、运维)

应用更快速的交互和部署

传统:一堆帮助文档,安装程序

Docker:打包镜像发布测试,一件运行

更快捷的升级和扩缩容

部署应用就像搭积木

项目打包为镜像,扩展,服务器 A,服务器 B

更简单的系统运维

开发测试环境高度一致

更高效的计算资源利用

Docker 是内核级虚拟化,一个物理机可运行很多容器实例

Docker 安装

Docker 基本组成

镜像(image)

一个模板,可以通过这个模板来创建容器服务。tomcat 镜像== >run===>tomcat01 容器,通过这个惊喜可以创建多个容器

容器(container)

Docker 利用容器技术,独立运行一个或一组应用

仓库(repository)

存放镜像的地方。分为共有仓库和私有仓库

Docker Hub 默认为国外的,可以使用国内地址加速

安装 Docker

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
# 官网:https://docs.docker.com/get-docker/

# Mac
brew cask install docker

# Centos
# 卸载老版本
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
# 设置存储库
sudo yum install -y yum-utils
sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
# 安装Docker引擎
sudo yum install docker-ce docker-ce-cli containerd.io
# 安装docker-compose
sudo curl -L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
# 启动Docker
sudo systemctl start docker
# 运行hello-world
sudo docker run hello-world

# 镜像加速
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://qtpwk07g.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

HelloWorld 流程

底层原理

  • Docker 是一个 Server-Client 架构的系统,Docker 守护进程运行在主机上,通过 Client 访问

  • 为什么 Docker 比 VM 快?
    • Docker 有着比虚拟机更少的抽象层
    • Docker 利用宿主机内核,VM 需要 Guest OS

  • Docker && LXC && VM 对比
    Docker 容器LXCVM
    虚拟化类型OS 虚拟化OS 虚拟化硬件虚拟化
    性能物理机性能物理机性能5%–20%损耗
    隔离型NS 隔离NS 隔离
    QoSCgroup 弱Cgroup 弱
    安全性
    GuestOS全部只支持 Linux全部
    可迁移性

Docker 常用命令

帮助命令

帮助文档地址:https://docs.docker.com/engine/reference/commandline/

1
2
3
4
5
6
# 查看版本信息
docker version
# 显示docker系统信息,包括镜像
docker info
# 万能命令
docker 命令 --help

镜像命令

docker images

  • 查看本地所有主机上的镜像
1
2
3
4
5
6
7
[root@server1 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql latest dd7265748b5d 9 days ago 545MB
hello-world latest bf756fb1ae65 11 months ago 13.3kB
# 可选项
-a, -all # 列出所有镜像
-q, -quiet # 只显示镜像id
  • 搜索镜像
1
2
3
4
5
6
7
8
9
[root@server1 ~]# docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 10202 [OK]
mariadb MariaDB is a community-developed fork of MyS… 3753 [OK]
mysql/mysql-server Optimized MySQL Server Docker images. Create… 746 [OK]
percona Percona Server is a fork of the MySQL relati… 511 [OK]

# 可选项
--filter=STARS=3000 # 搜索出来的镜像STARS大于3000

docker pull

  • 下载镜像
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
[root@server1 ~]# docker pull tomcat
Using default tag: latest
latest: Pulling from library/tomcat # 不写tag默认为latest
756975cb9c7e: Pull complete # 分层下载,docker image的核心,联合文件系统
d77915b4e630: Pull complete
5f37a0a41b6b: Pull complete
96b2c1e36db5: Pull complete
27a2d52b526e: Pull complete
a867dba77389: Pull complete
0939c055fb79: Pull complete
0b0694ce0ae2: Pull complete
81a5f8099e05: Pull complete
c3d7917d545e: Pull complete
Digest: sha256:a319b10d8729817c7ce0bcc2343a6f97711c7870395019340d96b6aafd6ccbea # 签名
Status: Downloaded newer image for tomcat:latest
docker.io/library/tomcat:latest #真实地址

docker pull tomcat === docker pull docker.io/library/tomcat:latest


[root@server1 ~]# docker pull mysql:5.7
5.7: Pulling from library/mysql
852e50cd189d: Already exists # 联合文件系统,已存在的不需要再下载
29969ddb0ffb: Already exists
a43f41a44c48: Already exists
5cdd802543a3: Already exists
b79b040de953: Already exists
938c64119969: Already exists
7689ec51a0d9: Already exists
36bd6224d58f: Pull complete
cab9d3fa4c8c: Pull complete
1b741e1c47de: Pull complete
aac9d11987ac: Pull complete
Digest: sha256:8e2004f9fe43df06c3030090f593021a5f283d028b5ed5765cc24236c2c4d88e
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7

docker rmi

  • 删除镜像
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 删除指定id的镜像
[root@server1 ~]# docker rmi -f ae0658fdbad5
Untagged: mysql:5.7
Untagged: mysql@sha256:8e2004f9fe43df06c3030090f593021a5f283d028b5ed5765cc24236c2c4d88e
Deleted: sha256:ae0658fdbad5fb1c9413c998d8a573eeb5d16713463992005029c591e6400d02
Deleted: sha256:a2cf831f4221764f4484ff0df961b54f1f949ed78220de1b24046843c55ac40f
Deleted: sha256:0a7adcc95a91b1ec2beab283e0bfce5ccd6df590bd5a5e894954fcf27571e7f5
Deleted: sha256:0fae465cbacf7c99aa90bc286689bc88a35d086f37fd931e03966d312d5dfb10
Deleted: sha256:23af125b9e54a94c064bdfacc2414b1c8fba288aff48308e8117beb08b38cb19

# 删除多个镜像
[root@server1 ~]# docker rmi -f imageid1, imageid2,imageid3

# 删除所有镜像
# 可命令嵌套
[root@server1 ~]# docker rmi -f $(docker images -aq)

容器命令

docker run

  • 开启新容器并运行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 先ntos镜像
docker pull centos

# 新建容器并启动
docker run [可选参数] image
# 参数说明
--name="Name" # 指定容器名字
-d # 后台方式运行
-i # 使用交互方式运行,进入容器查看内容
-p # 指定容器端口
-p ip:主机端口 : 容器端口
-p 主机端口 : 容器端口
-p 容器端口
-P # 指定随机端口

# 测试、启动并进入容器
[root@server1 ~]# docker run -it centos /bin/bash
# 使用
[root@cd3299fcc032 /]# ls
bin etc lib lost+found mnt proc run srv tmp var
dev home lib64 media opt root sbin sys usr

docker ps

  • 查看运行的容器
1
2
3
4
5
# 查看正在运行的容器
[root@server1 ~]# docker ps [可选参数
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
-a # 示所有容器
-n=7 # 显示最近7个容器

exit

  • 退出
1
2
3
4
5
# 退出容器且停止运行
[root@cd3299fcc032 opt]# exit
exit
# 退出容器且继续运行
Ctrl + P + Q

docker rm

  • 删除容器
1
2
3
4
5
6
# 删除指定id容器
docker rm 容器id
-f # 强制执行
# 删除所有容器
docker rm -f $(docker ps -aq)
docker ps -a -q | xargs docker rm

docker start/restart/stop/kill

1
2
3
4
5
6
7
8
# 启动容器
docker start 容器id
# 重启容器
docker restart 容器id
# 停止当前正在运行的容器
docker stop 容器id
# 强制停止当前容器
docker kill 容器id

其他常用

1、后台启动容器

1
2
3
4
5
6
[root@server1 ~]# docker run -d centos
a2e2c9f87dc9dea7a04221c4e159a71364e752cb572ee8c6a9722defc2a9713f
[root@server1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@server1 ~]#
# 常见的坑:docker容器使用后台运行,必须有一个前台进程。docker没有发现应用,就自动停止

2、查看日志

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[root@server1 ~]# docker logs --help
Usage: docker logs [OPTIONS] CONTAINER
Fetch the logs of a container

Options:
--details Show extra details provided to logs
-f, --follow Follow log output
--since string Show logs since timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)
-n, --tail string Number of lines to show from the end of the logs (default "all")
-t, --timestamps Show timestamps
--until string Show logs before a timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)

[root@server1 ~]# docker run -d centos /bin/sh -c "while true;do echo lqs;sleep 1;done"
1d99006b4363eabcf1f33e5eec16fd45059dd5cdd400e6e05b3300fcd7b5e094
[root@server1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1d99006b4363 centos "/bin/sh -c 'while t…" 4 seconds ago Up 2 seconds sweet_pascal
4a48763c24a9 centos "/bin/sh -c 'while t…" 2 minutes ago Up 2 minutes cool_knuth
[root@server1 ~]# docker logs -tf --tail 10 1d99006b4363
2020-11-30T06:24:34.441977721Z lqs
2020-11-30T06:24:35.459814107Z lqs
2020-11-30T06:24:36.487265008Z lqs
2020-11-30T06:24:37.508551064Z lqs
2020-11-30T06:24:38.526719550Z lqs

3、查看进程信息

1
2
3
4
[root@server1 ~]# docker top 1d99006b4363
UID PID PPID C STIME TTY TIME CMD
root 476469 476326 0 14:24 ? 00:00:00 /bin/sh -c while true;do echo lqs;sleep 1;done
root 583733 476469 0 14:29 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1

4、查看元数据

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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209

[root@server1 ~]# docker inspect 1d99006b4363
[
{
"Id": "1d99006b4363eabcf1f33e5eec16fd45059dd5cdd400e6e05b3300fcd7b5e094",
"Created": "2020-11-30T06:24:24.660296498Z",
"Path": "/bin/sh",
"Args": [
"-c",
"while true;do echo lqs;sleep 1;done"
],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 476469,
"ExitCode": 0,
"Error": "",
"StartedAt": "2020-11-30T06:24:26.324713861Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:0d120b6ccaa8c5e149176798b3501d4dd1885f961922497cd0abef155c869566",
"ResolvConfPath": "/var/lib/docker/containers/1d99006b4363eabcf1f33e5eec16fd45059dd5cdd400e6e05b3300fcd7b5e094/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/1d99006b4363eabcf1f33e5eec16fd45059dd5cdd400e6e05b3300fcd7b5e094/hostname",
"HostsPath": "/var/lib/docker/containers/1d99006b4363eabcf1f33e5eec16fd45059dd5cdd400e6e05b3300fcd7b5e094/hosts",
"LogPath": "/var/lib/docker/containers/1d99006b4363eabcf1f33e5eec16fd45059dd5cdd400e6e05b3300fcd7b5e094/1d99006b4363eabcf1f33e5eec16fd45059dd5cdd400e6e05b3300fcd7b5e094-json.log",
"Name": "/sweet_pascal",
"RestartCount": 0,
"Driver": "overlay2",
"Platform": "linux",
"MountLabel": "",
"ProcessLabel": "",
"AppArmorProfile": "",
"ExecIDs": null,
"HostConfig": {
"Binds": null,
"ContainerIDFile": "",
"LogConfig": {
"Type": "json-file",
"Config": {}
},
"NetworkMode": "default",
"PortBindings": {},
"RestartPolicy": {
"Name": "no",
"MaximumRetryCount": 0
},
"AutoRemove": false,
"VolumeDriver": "",
"VolumesFrom": null,
"CapAdd": null,
"CapDrop": null,
"CgroupnsMode": "host",
"Dns": [],
"DnsOptions": [],
"DnsSearch": [],
"ExtraHosts": null,
"GroupAdd": null,
"IpcMode": "private",
"Cgroup": "",
"Links": null,
"OomScoreAdj": 0,
"PidMode": "",
"Privileged": false,
"PublishAllPorts": false,
"ReadonlyRootfs": false,
"SecurityOpt": null,
"UTSMode": "",
"UsernsMode": "",
"ShmSize": 67108864,
"Runtime": "runc",
"ConsoleSize": [
0,
0
],
"Isolation": "",
"CpuShares": 0,
"Memory": 0,
"NanoCpus": 0,
"CgroupParent": "",
"BlkioWeight": 0,
"BlkioWeightDevice": [],
"BlkioDeviceReadBps": null,
"BlkioDeviceWriteBps": null,
"BlkioDeviceReadIOps": null,
"BlkioDeviceWriteIOps": null,
"CpuPeriod": 0,
"CpuQuota": 0,
"CpuRealtimePeriod": 0,
"CpuRealtimeRuntime": 0,
"CpusetCpus": "",
"CpusetMems": "",
"Devices": [],
"DeviceCgroupRules": null,
"DeviceRequests": null,
"KernelMemory": 0,
"KernelMemoryTCP": 0,
"MemoryReservation": 0,
"MemorySwap": 0,
"MemorySwappiness": null,
"OomKillDisable": false,
"PidsLimit": null,
"Ulimits": null,
"CpuCount": 0,
"CpuPercent": 0,
"IOMaximumIOps": 0,
"IOMaximumBandwidth": 0,
"MaskedPaths": [
"/proc/asound",
"/proc/acpi",
"/proc/kcore",
"/proc/keys",
"/proc/latency_stats",
"/proc/timer_list",
"/proc/timer_stats",
"/proc/sched_debug",
"/proc/scsi",
"/sys/firmware"
],
"ReadonlyPaths": [
"/proc/bus",
"/proc/fs",
"/proc/irq",
"/proc/sys",
"/proc/sysrq-trigger"
]
},
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/e43e6b4eee920ace4ce359c795615e673ba50bb70cee790a86d8feb26c999fa9-init/diff:/var/lib/docker/overlay2/591ddae90babb77b4ea29561acc558e678b309edbb5b91112a566c9c1fb48367/diff",
"MergedDir": "/var/lib/docker/overlay2/e43e6b4eee920ace4ce359c795615e673ba50bb70cee790a86d8feb26c999fa9/merged",
"UpperDir": "/var/lib/docker/overlay2/e43e6b4eee920ace4ce359c795615e673ba50bb70cee790a86d8feb26c999fa9/diff",
"WorkDir": "/var/lib/docker/overlay2/e43e6b4eee920ace4ce359c795615e673ba50bb70cee790a86d8feb26c999fa9/work"
},
"Name": "overlay2"
},
"Mounts": [],
"Config": {
"Hostname": "1d99006b4363",
"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/sh",
"-c",
"while true;do echo lqs;sleep 1;done"
],
"Image": "centos",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {
"org.label-schema.build-date": "20200809",
"org.label-schema.license": "GPLv2",
"org.label-schema.name": "CentOS Base Image",
"org.label-schema.schema-version": "1.0",
"org.label-schema.vendor": "CentOS"
}
},
"NetworkSettings": {
"Bridge": "",
"SandboxID": "b7d79cfaf7ee2a80d7186625f73561987096a77d40022d9da8a15325f833908e",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {},
"SandboxKey": "/var/run/docker/netns/b7d79cfaf7ee",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "82568b40df9a9923ae2599d54adba35f7231ee42f1712781da5549e5333a4332",
"Gateway": "172.18.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "172.18.0.3",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"MacAddress": "02:42:ac:12:00:03",
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "fc51f6980ccad65f81ddef3584c7a7f3b80df21521fc322d204f1eaf9b9383a0",
"EndpointID": "82568b40df9a9923ae2599d54adba35f7231ee42f1712781da5549e5333a4332",
"Gateway": "172.18.0.1",
"IPAddress": "172.18.0.3",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:12:00:03",
"DriverOpts": null
}
}
}
}
]

5、进入当前正在运行的容器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 方式一
# 一般后台运行,需要进入容器修改一些配置
[root@server1 ~]# docker exec -it 1d99006b4363 /bin/bash
- exec # 进入容器
-it # 交互模式
[root@1d99006b4363 /]# ls
bin etc lib lost+found mnt proc run srv tmp var
dev home lib64 media opt root sbin sys usr
[root@1d99006b4363 /]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 06:24 ? 00:00:00 /bin/sh -c while true;do
root 847 0 0 06:38 pts/0 00:00:00 /bin/bash
root 926 1 0 06:39 ? 00:00:00 /usr/bin/coreutils --cor
root 927 847 0 06:39 pts/0 00:00:00 ps -ef

# 方式二
[root@server1 ~]# docker attach 1d99006b4363
lqs
lqs


# 比较
# docker exec 进入容器后开启新终端,可以直接操作
# docker attach 进入容器正在执行的终端,不会启动新进程

6、从容器拷贝文件到主机

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# docker cp 2973e8f2a4c1:/home/new.java  /home

[root@server1 ssh]# docker attach 2973e8f2a4c1
[root@2973e8f2a4c1 /]# cd /home/
[root@2973e8f2a4c1 home]# ls
lqs.java
[root@2973e8f2a4c1 home]# touch new.java
[root@2973e8f2a4c1 home]# ls
lqs.java new.java
[root@2973e8f2a4c1 home]# read escape sequence
[root@server1 ssh]# cd
[root@server1 ~]# cd /home/
[root@server1 home]# ls
admin lqs.java
[root@server1 home]# docker cp 2973e8f2a4c1:/home/new.java /home
[root@server1 home]# ls
admin lqs.java new.java
[root@server1 home]#

7、测试用例

1
2
# 测试用例,用完自动删
[root@server1 ssh]# docker run -it --rm tomcat:9.0

8、可视化

  • portainer
1
2
docker run -d -p 8088:9000 \
--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
  • rancher

小结

作业

安装 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
44
45
46
47
48
49
[root@server1 home]# docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
852e50cd189d: Pull complete
571d7e852307: Pull complete
addb10abd9cb: Pull complete
d20aa7ccdb77: Pull complete
8b03f1e11359: Pull complete
Digest: sha256:6b1daa9462046581ac15be20277a7c75476283f969cb3a61c8725ec38d3b01c3
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest
[root@server1 home]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest bc9a0695f571 5 days ago 133MB
centos latest 0d120b6ccaa8 3 months ago 215MB
[root@server1 home]# docker run -d --name nginx01 -p 3344:80 nginx
730596a510eb00386fc0c2de680f1379bbee497c70f676df1588d635e944c115
[root@server1 home]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
730596a510eb nginx "/docker-entrypoint.…" 4 seconds ago Up 3 seconds 0.0.0.0:3344->80/tcp nginx01
2973e8f2a4c1 centos "/bin/bash" 5 hours ago Up 25 minutes gallant_shirley
# 访问nginx
[root@server1 home]# curl localhost:3344
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
[root@server1 home]#

部署 ElasticSearch + Kibana

  • ES 端口暴露多
  • 十分耗内存
  • ES 数据一般放置在安全目录
  • –net somenetwork 网络配置
1
2
3
4
[root@server1 home]# docker run -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.9.3

# ES占用内存太大,修改JVM参数
[root@server1 home]# docker run -d --name elasticsearch01 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.9.3

Docker 镜像

镜像

是一种轻量级、可执行的独立软件包。用来打包软件运行环境和基于运行环境开发的软件,包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。所有应用,直接打包 docker 镜像,就可以直接运行

Docker 镜像加载原理

UnionFS 文件系统

UnionFS(联合文件系统): Union 文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union 文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承, 基于基础镜像(没有父镜像), 可以制作各种具体的应用镜像。
特性: 一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。

Docker 镜像加载原理

bootfs(boot file system)主要包含 bootloader 和 kernel,bootloader 主要是引导加载 kernel,Linux 刚启动时会加载 bootfs 文件系统,在 Docker 镜像的最底层是 bootfs。这一层与我们典型的 Linux/Unix 系统是一样的, 包含 boot 加载器和内核。当 boot 加载完成之后整个内核就都在内存中了,此时内存的使用权已由 bootfs 转交给内核,此时系统也会卸载 bootfs。

rootfs(root file system), 在 bootfs 之上。包含的就是典型 Linux 系统中的/dev, /proc, /bin, /etc 等标准目录和文件。rootfs 就是各种不同的操作系统发行版,比如 Ubuntu,Centos 等等。

对于一个精简的 OS,rootfs 可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用 Host 的 kernel,自己只需要提供 rootfs 就行了。由此可见对于不同的 linux 发行版,bootfs 基本是一致的,rootfs 会有差别,因此不同的发行版可以共用 bootfs。

分层的镜像

以我们的 pull 为例,在下载的过程中我们可以看到 docker 的镜像好像是在一层一层的在下载

分层好处

共享资源
比如:有多个镜像都从相同的 base 镜像构建而来,那么宿主机只需在磁盘上保存一份 base 镜像,同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。

Docker 镜像特点

Docker 镜像都是只读的
当容器启动时,一个新的可写层被加载到镜像的顶部。
这一层通常被称作为”容器层”,“容器层”之下的都叫”镜像层”。

Commit 镜像

1
2
3
4
docker commit 类似于git
# 提交容器成为一个新的镜像

docker commit -m="描述信息" -a="作者" 容器id 目标镜像名:[tag]

Docker 数据卷

容器数据卷:能将数据可持久化,删除容器时可不删除存放的数据

方式一:-v 挂载

基本概念

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 将新建的 centos 容器的/home 目录挂载在主机上/home/ceshi 文件夹进行**双向绑定**

docker run -it -v /home/ceshi:/home centos /bin/bash

# 在主机上使用 docker inspect id 查看数据卷挂载

"Mounts": [
{
"Type": "bind",
"Source": "/home/ceshi",
"Destination": "/home",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],

实战:持久化 MySQL

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 进行配置

[root@server1 home]# docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
-d 后台运行
-p 端口
-v 数据卷挂载
-e 环境
--name 名字

# 远程登录

🐂🍺 mysql -haly -P3310 -uroot -p

# 此时删除容器,主机上的目录依然存在

具名/匿名挂载

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
# 匿名挂载

# -v 容器内路径

docker run -d -P --name nginx01 -v /etc/nginx nginx

# 具名挂载

# -v 卷名:容器内路径

# 默认挂载地址:/var/lib/docker/volumes/juming/\_data

[root@server1 data]# docker run -d -P --name nginx01 -v juming:/etc/nginx nginx
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
852e50cd189d: Already exists
571d7e852307: Pull complete
addb10abd9cb: Pull complete
d20aa7ccdb77: Pull complete
8b03f1e11359: Pull complete
Digest: sha256:6b1daa9462046581ac15be20277a7c75476283f969cb3a61c8725ec38d3b01c3
Status: Downloaded newer image for nginx:latest
f4b4012c0245d5c7c32010b6cefdf14ab82ccd4eb7441201b13f38429022e121

# 查看所有卷:docker volume ls

[root@server1 data]# docker volume ls
DRIVER VOLUME NAME
local 9a7e9a5a0533594193bd5711b1f52899f22f5ed9d7c09a18356455a8a270fbcd
local juming

# 查看卷名元数据:docker volume inspect juming

[root@server1 data]# docker volume inspect juming
[
{
"CreatedAt": "2020-12-01T15:43:14+08:00",
"Driver": "local",
"Labels": null,
# 本地存储位置
"Mountpoint": "/var/lib/docker/volumes/juming/_data",
"Name": "juming",
"Options": null,
"Scope": "local"
}
]
  • 拓展
1
2
3
4
5
6
7
# 通过-v 指定容器内路径及读写权限

# ro: 只读,只能通过宿主机改变,容器内部不能修改

# rw:可读可写(default)

-v 卷名:路径:ro/rw

初识 DockerFile

实际就是 imageFile,构建 Docker 镜像的构建脚本

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
[root@server1 docker-test-volume]# vim dockerfile1

FROM centos

VOLUME ["volume01","volume02"]

CMD echo "===end==="
CMD /bin/bash

[root@server1 docker-test-volume]# docker build -f dockerfile1 -t lqs/centos:1.0 .
Sending build context to Docker daemon 2.048kB
Step 1/4 : FROM centos
---> 0d120b6ccaa8
Step 2/4 : VOLUME ["volume01","volume02"]
---> Running in 139b85666b23
Removing intermediate container 139b85666b23
---> 5ba70f0b2c01
Step 3/4 : CMD echo "===end==="
---> Running in b7b3d3d10528
Removing intermediate container b7b3d3d10528
---> a2f5c60a54e0
Step 4/4 : CMD /bin/bash
---> Running in b7a8f6f55f83
Removing intermediate container b7a8f6f55f83
---> 1153bee64870
Successfully built 1153bee64870
Successfully tagged lqs/centos:1.0
[root@server1 docker-test-volume]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
lqs/centos 1.0 1153bee64870 9 seconds ago 215MB
nginx latest bc9a0695f571 6 days ago 133MB
mysql 5.7 ae0658fdbad5 10 days ago 449MB
centos latest 0d120b6ccaa8 3 months ago 215MB
  • 可以看到生存镜像是自动给挂载的数据卷
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[root@server1 docker-test-volume]# docker run -it 1153bee64870 /bin/bash
[root@1e6c5ff18e75 /]# ls -l
total 0
lrwxrwxrwx 1 root root 7 May 11 2019 bin -> usr/bin
drwxr-xr-x 5 root root 360 Dec 1 08:20 dev
drwxr-xr-x 1 root root 66 Dec 1 08:20 etc
drwxr-xr-x 2 root root 6 May 11 2019 home
lrwxrwxrwx 1 root root 7 May 11 2019 lib -> usr/lib
lrwxrwxrwx 1 root root 9 May 11 2019 lib64 -> usr/lib64
drwx------ 2 root root 6 Aug 9 21:40 lost+found
drwxr-xr-x 2 root root 6 May 11 2019 media
drwxr-xr-x 2 root root 6 May 11 2019 mnt
drwxr-xr-x 2 root root 6 May 11 2019 opt
dr-xr-xr-x 118 root root 0 Dec 1 08:20 proc
dr-xr-x--- 2 root root 162 Aug 9 21:40 root
drwxr-xr-x 11 root root 163 Aug 9 21:40 run
lrwxrwxrwx 1 root root 8 May 11 2019 sbin -> usr/sbin
drwxr-xr-x 2 root root 6 May 11 2019 srv
dr-xr-xr-x 13 root root 0 Dec 1 08:20 sys
drwxrwxrwt 7 root root 145 Aug 9 21:40 tmp
drwxr-xr-x 12 root root 144 Aug 9 21:40 usr
drwxr-xr-x 20 root root 262 Aug 9 21:40 var
drwxr-xr-x 2 root root 6 Dec 1 08:20 volume01
drwxr-xr-x 2 root root 6 Dec 1 08:20 volume02

数据卷容器

  • 实现多容器数据共享
1
2
3
4
5
# 这样docker02和docker03的文件随docker01文件的改变而改变
[root@server1 /]# docker run -it --name docker02 --volumes-from docker01 lqs/centos:1.0
[root@server1 /]# docker run -it --name docker03 --volumes-from docker01 lqs/centos:1.0

- 但是删除docker01时docker02和docker03的文件依然存在,都存在宿主机文件中

注意:

容器之间配置信息的传递,一直持续到没有容器使用为止

一旦持久化到本地,本地数据不会删除

DockerFile

构建 DockerImage 镜像的文件,是命令参数脚本,定义一切步骤和源代码

面向开发,逐渐成为企业交付的标准。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
- 注意:

# 每个关键字必须大写

# 执行从上到下按序执行

- 1、编写一个 dockerfile 文件
- 2、docker build 构建镜像
- 3、docker run 运行镜像
- 4、docker push 发布镜像到 DockerHub or 阿里云镜像仓库

# #表示注释

# 每个指令都表示一个新的镜像层,并提交

DockerFile 命令

1
2
3
4
5
6
7
8
9
10
11
12
- FROM 基础镜像,一起从这里开始
- MAINTAINER 作者,姓名+邮箱
- RUN 镜像构建的时候需要运行的命令
- ADD tomcat 镜像
- WORKDIR 镜像工作目录
- VOLUME 挂载目录
- EXPOSE 保留端口配置
- CMD 指定容器启动时运行的指令,只有最后一个会生效,可被替代
- ENTRYPOINT 指定容器启动时运行的指令,可以追加命令
- ONBUILD 触发指令:当构建一个被挤成 DockerFile,这个时候就运行
- COPY 类似 ADD,将文件拷贝到镜像中
- ENV 环境变量

例子:构建个人 centos

编写配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@server1 docker-test-volume]# vim dockerfile-centos
FROM centos
MAINTAINER lqs<polarisink@163.com>

ENV MYPATH /usr/local
WORKDIR $MYPATH

RUN yum -y install vim
RUN yum -y install net-tools

EXPOSE 80

CMD echo $MYPATH
CMD echo "-----end----"
CMD /bin/bash

通过文件构建镜像(.不能少)

1
2
3
[root@server1 docker-test-volume]# docker build -f dockerfile-centos -t mycentos:0.1 .
Successfully built 69a888bf8bdb
Successfully tagged mycentos:0.1

测试运行(vim 和 ifconfig 可以使用)

查看历史

CMD && ENTRYPOINT

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
# CMD						指定容器启动时运行的指令,只有最后一个会生效,可被替代
# ENTRYPOINT 指定容器启动时运行的指令,可以追加命令

[root@server1 docker-test-volume]# cat dockerfile-cmd-test
FROM centos

CMD ["ls", "-a"]

[root@server1 docker-test-volume]# cat dockerfile-entrypoint-test
FROM centos

ENTRYPOINT ["ls", "-a"]
# 不能追加命令
[root@server1 docker-test-volume]# docker run cmdtest -l
docker: Error response from daemon: OCI runtime create failed: container_linux.go:370: starting container process caused: exec: "-l": executable file not found in $PATH: unknown.
# 可以追加命令
[root@server1 docker-test-volume]# docker run mycentos-entrypoint -l
total 0
drwxr-xr-x 1 root root 6 Dec 2 05:32 .
drwxr-xr-x 1 root root 6 Dec 2 05:32 ..
-rwxr-xr-x 1 root root 0 Dec 2 05:32 .dockerenv
lrwxrwxrwx 1 root root 7 May 11 2019 bin -> usr/bin
drwxr-xr-x 5 root root 340 Dec 2 05:32 dev
drwxr-xr-x 1 root root 66 Dec 2 05:32 etc
drwxr-xr-x 2 root root 6 May 11 2019 home
lrwxrwxrwx 1 root root 7 May 11 2019 lib -> usr/lib
lrwxrwxrwx 1 root root 9 May 11 2019 lib64 -> usr/lib64
drwx------ 2 root root 6 Aug 9 21:40 lost+found
drwxr-xr-x 2 root root 6 May 11 2019 media
drwxr-xr-x 2 root root 6 May 11 2019 mnt
drwxr-xr-x 2 root root 6 May 11 2019 opt
dr-xr-xr-x 125 root root 0 Dec 2 05:32 proc
dr-xr-x--- 2 root root 162 Aug 9 21:40 root
drwxr-xr-x 11 root root 163 Aug 9 21:40 run
lrwxrwxrwx 1 root root 8 May 11 2019 sbin -> usr/sbin
drwxr-xr-x 2 root root 6 May 11 2019 srv
dr-xr-xr-x 13 root root 0 Dec 2 05:32 sys
drwxrwxrwt 7 root root 145 Aug 9 21:40 tmp
drwxr-xr-x 12 root root 144 Aug 9 21:40 usr
drwxr-xr-x 20 root root 262 Aug 9 21:40 var
[root@server1 docker-test-volume]#

实战:构建 Tomcat 镜像

1、准备镜像文件

  • tomcat 压缩包,jdk 压缩包,readme.txt
1
2
[root@server1 tomcat]# ls
apache-tomcat-8.5.54.tar.gz jdk-8u271-linux-x64.tar.gz readme.txt

2、编写Dockerfile

  • 官方推荐名字,可以自动寻找
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
[root@server1 tomcat]# vim Dockerfile


FROM centos
MAINTAINER polarisink<polarisink@163.com>
# 复制文件
COPY readme.txt /usr/local/readme.txt
# 增加,会自动解压
ADD jdk-8u271-linux-x64.tar.gz /usr/local
ADD apache-tomcat-8.5.54.tar.gz /usr/local

RUN yum -y install vim

ENV MYPATH /usr/local
WORKDIR $MYPATH
# 配置环境变量
ENV JAVA_HOME /usr/local/jdk1.8.0_271
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.54
ENV CATALINA_BASH /usr/local/apache-tomcat-8.5.54
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin

EXPOSE 8080

CMD /usr/local/apache-tomcat-8.5.54/bin/startup.sh && tail -F /usr/local/apache-tomcat-8.5.54/bin/logs/catalina.out

3、build 镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@server1 tomcat]# docker build -t diytomcat .
Sending build context to Docker daemon 153.5MB
Step 1/15 : FROM centos
---> 0d120b6ccaa8
Step 2/15 : MAINTAINER polarisink<polarisink@163.com>
---> Running in 38b244f6ae39
Removing intermediate container 38b244f6ae39
---> 7df638db0336
Step 3/15 : COPY readme.txt /usr/local/readme.txt
---> 4d8f3f2150ab
Step 4/15 : ADD jdk-8u271-linux-x64.tar.gz /usr/local
---> 9e75aa75f839
Step 5/15 : ADD apache-tomcat-8.5.54.tar.gz /usr/local
---> 613500475b41
Step 6/15 : RUN yum -y install vim

Step 15/15 : CMD /usr/local/apache-tomcat-8.5.54/bin/startup.sh && tail -F /usr/local/apache-tomcat-8.5.54/bin/logs/catalina.out
—> Running in 1a5e363f4779
Removing intermediate container 1a5e363f4779
—> 311502a899e6
Successfully built 311502a899e6
Successfully tagged diytomcat:latest

1
2
3
4
5
6
7

### 4、启动镜像

```shell
# 挂载两个目录
[root@server1 tomcat]# docker run -d -p 9090:8080 --name polaristomcat -v /home/ceshi/tomcat/test:/usr/local/apache-tomcat-8.5.54/webapps/test -v /home/ceshi/tomcat/tomcatlogs/:/uar/local/apache-tomcat-8.5.54/logs diytomcat
7b4e433ae6c695d8290b58e8ea517cca12232bdc89a1f4dd2df695ec4ce6a18c

5、访问测试

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@server1 tomcat]# curl localhost:9090



<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Apache Tomcat/8.5.54</title>
<link href="favicon.ico" rel="icon" type="image/x-icon" />
<link href="favicon.ico" rel="shortcut icon" type="image/x-icon" />
<link href="tomcat.css" rel="stylesheet" type="text/css" />
</head>

6、发布项目

1
2
3
4
5
6
7
8
9
10
[root@server1 ~]# cd /home/ceshi/tomcat/test/
[root@server1 test]# ls
index.jsp WEB-INFO
[root@server1 test]# docker run -d -p 9090:8080 --name polaristomcat2 -v /home/ceshi/tomcat/test:/usr/local/apache-tomcat-8.5.54/webapps/test -v /home/ceshi/tomcat/tomcatlogs:/usr/local/apache-tomcat-8.5.54/logs diytomcat
[root@server1 ~]# cat /home/ceshi/tomcat/tomcatlogs/catalina.out
02-Dec-2020 07:09:02.863 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/usr/local/apache-tomcat-8.5.54/webapps/test] has finished in [60] ms
02-Dec-2020 07:09:02.879 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-8080"]
02-Dec-2020 07:09:02.925 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 1618 ms
--my test web logs---
--my test web logs---

发布个人镜像

  1. 登录DockerHub
  2. 在服务器上登录 dockerhub
1
2
3
4
5
6
7
[root@server1 tomcatlogs]# docker login -u polarisink
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded
  1. 提交镜像到 dockerhub
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@server1 tomcatlogs]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
diytomcat latest 311502a899e6 About an hour ago 642MB
mycentos-entrypoint latest 72d222203c8b 2 hours ago 215MB
cmdtest latest 09422ecb6cde 2 hours ago 215MB
mycentos 0.1 69a888bf8bdb 3 hours ago 295MB
lqs/centos 1.0 1153bee64870 23 hours ago 215MB
nginx latest bc9a0695f571 7 days ago 133MB
mysql 5.7 ae0658fdbad5 11 days ago 449MB
centos latest 0d120b6ccaa8 3 months ago 215MB
# push可以使用tag重命名
[root@server1 tomcatlogs]# docker tag 311502a899e6 polarisink/tomcat:1.0
[root@server1 tomcatlogs]# docker push polarisink/tomcat:1.0
The push refers to repository [docker.io/polarisink/tomcat]
96030ed24189: Pushing 11.35MB/57.24MB
d6314d23ddb4: Pushing 2.111MB/14.45MB
0d60766e4c76: Pushing 3.857MB/355.3MB
264590514375: Pushed
291f6e44771a: Pushing 6.561MB/215.1MB
  1. 提交到阿里云镜像仓库
  • 注册命名空间和仓库

  • 基本信息
1
2
3
4
5
6
7
8
# 登陆阿里云容器镜像服务
$ sudo docker login --username=lxl520lqs registry.cn-hangzhou.aliyuncs.com
# pull镜像
$ sudo docker pull registry.cn-hangzhou.aliyuncs.com/polarsink/kuangshendocker:[镜像版本号]
# 给镜像起名
$ sudo docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/polarsink/kuangshendocker:[镜像版本号]
# push镜像
$ sudo docker push registry.cn-hangzhou.aliyuncs.com/polarsink/kuangshendocker:[镜像版本号]

Docker 网络

Docker0

1、准备和观察

1
2
3
4
5
6
# 先环境清零
docker rm -f $(docker ps -aq)
docker rmi $(docker images -q)
docker volume rm $(docker volume ls -q)

# 查看网卡

  • 查看容器内部网络

  • Linux 主机可以 ping 通容器内部

1
2
3
4
5
6
7
- 安装 Docker 时,系统给 Docker 分配一个 docker0 网卡
- 每当启动一个 Docker 容器,Docker 就会给 Docker 容器分配一个 ip
5: vethf6beca6@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 36:bf:79:d7:66:46 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::34bf:79ff:fed7:6646/64 scope link
valid_lft forever preferred_lft forever
- 使用桥接模式,采用 evth-pair 技术

![](/Users/lqs/Library/Application Support/typora-user-images/image-20201204205621273.png)

1
2
3
4
5
6
7
8
9
10
11
# evth-pair

- 一对对的虚拟设备接口,成对出现
- 一段连着协议,一段连接彼此
- 用来充当桥梁,连接各种虚拟网络设备

# 结论

- 所有容器在不指定网络的情况下,都使用 docker 作为路由器
- docker0 为容器 A 和容器 B 分配一个默认可用的 IP
- 当删除容器时虚拟网卡会删除

作用:端口绑定,将 link 写入/etc/hosts

现在一般放弃使用,因为默认使用 docker0 网卡,不能自定义

docker0 不支持容器名连接访问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@server1 blog]# docker run -d -P --name tomcat04 --link tomcat03 tomcat
b46b2485ff5c82cf7ca7ad394f30cbb1cc80dfcc407980105ef08a6a3c033c5f
[root@server1 blog]# docker exec -it tomcat04 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

# 可以发现 tomcat03 的 ip 被写入 hosts 文件中

172.18.0.4 tomcat03 0f3204836c34
172.18.0.5 b46b2485ff5c
[root@server1 blog]#

自定义网络

网络模式

1
2
3
4
5
6
7
# bridge:桥接网络(默认,自定义也使用此方式)

# none:不配置网络

# host:和宿主机共享网络

# container:容器网络连接(用得少,局限性大)

自定义网络

docker network create

好处:不同集群使用不同的网络,保证集群的安全和健康

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
[root@server1 ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
68db8c5bfd01e7237a19d9cc2aaec9e0199c2690de3926065a16d89224de3250
[root@server1 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
e2e8121885a1 blog_default bridge local
e7745415748f bridge bridge local
998422bb93bb host host local
68db8c5bfd01 mynet bridge local
3a5d3fb4c291 none null local
[root@server1 ~]# docker network inspect mynet
[
{
"Name": "mynet",
"Id": "68db8c5bfd01e7237a19d9cc2aaec9e0199c2690de3926065a16d89224de3250",
"Created": "2020-12-05T11:14:01.64643517+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.0.0/16",
"Gateway": "192.168.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@server1 ~]# docker run -d -P --name tomcat-net-01 --net mynet tomcat
[root@server1 ~]# docker run -d -P --name tomcat-net-02 --net mynet tomcat
a65f9956dfa468e2f642c6d784172dac6beb81be0ca7170ca3c9417066b8ca0d

# 二者在同一子网,可以用名字互ping
[root@server1 ~]# docker exec -it tomcat-net-01 ping tomcat-net-02
PING tomcat-net-02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.115 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.084 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=3 ttl=64 time=0.063 ms
^C
--- tomcat-net-02 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 39ms
rtt min/avg/max/mdev = 0.063/0.087/0.115/0.022 ms
[root@server1 ~]#
  • 跨网络互 ping
1
2
3
4
# 此时tomcat-net-01和tomcat01不在同一网络,不能互ping
# 需要docker network connect进行连接
[root@server1 ~]# docker exec -it tomcat01 ping tomcat-net-01
ping: tomcat-net-01: Name or service not known

部署 Redis 集群

  • 要求

  • 编写 shell 脚本创建 Redis 容器
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
# 创建网卡
docker network create redis --subnet 172.38.0.0/16

# 脚本
for port in $(seq 1 6);\
do \
mkdir -p /mydata/redis/node-${port}/conf
touch /mydata/redis/node-${port}/conf/redis.conf
cat << EOF >/mydata/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.38.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done

docker run -p 637${port}:6379 -p 1637${port}:16379 --name redis-${port} \
-v /mydata/redis/node-${port}/data:/data \
-v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.1${port} redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf; \

docker run -p 6376:6379 -p 16376:16379 --name redis-6 \
-v /mydata/redis/node-6/data:/data \
-v /mydata/redis/node-6/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf; \

# 创建集群
/data # redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 172.38.0.15:6379 to 172.38.0.11:6379
Adding replica 172.38.0.16:6379 to 172.38.0.12:6379
Adding replica 172.38.0.14:6379 to 172.38.0.13:6379
M: 0f5cca1448266f1afb8a2818229e73f716ccf3e4 172.38.0.11:6379
slots:[0-5460] (5461 slots) master
M: f86cd1e9ab3ef69d6c7da52dddc16091346f00d7 172.38.0.12:6379
slots:[5461-10922] (5462 slots) master
M: 2ceb335c841c7313ce9a14f664ce5f32d8a79a84 172.38.0.13:6379
slots:[10923-16383] (5461 slots) master
S: c30fdd6b0698566ed0fc043c267809a98353e5a0 172.38.0.14:6379
replicates 2ceb335c841c7313ce9a14f664ce5f32d8a79a84
S: 20ea2a40faaa3212237677d3adefe3fe543fa838 172.38.0.15:6379
replicates 0f5cca1448266f1afb8a2818229e73f716ccf3e4
S: 9d3e36fdff17d3b5f95e94024d2af63d8c19be32 172.38.0.16:6379
replicates f86cd1e9ab3ef69d6c7da52dddc16091346f00d7
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
..
>>> Performing Cluster Check (using node 172.38.0.11:6379)
M: 0f5cca1448266f1afb8a2818229e73f716ccf3e4 172.38.0.11:6379
slots:[0-5460] (5461 slots) master
1 additional replica(s)
M: f86cd1e9ab3ef69d6c7da52dddc16091346f00d7 172.38.0.12:6379
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
M: 2ceb335c841c7313ce9a14f664ce5f32d8a79a84 172.38.0.13:6379
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: 20ea2a40faaa3212237677d3adefe3fe543fa838 172.38.0.15:6379
slots: (0 slots) slave
replicates 0f5cca1448266f1afb8a2818229e73f716ccf3e4
S: 9d3e36fdff17d3b5f95e94024d2af63d8c19be32 172.38.0.16:6379
slots: (0 slots) slave
replicates f86cd1e9ab3ef69d6c7da52dddc16091346f00d7
S: c30fdd6b0698566ed0fc043c267809a98353e5a0 172.38.0.14:6379
slots: (0 slots) slave
replicates 2ceb335c841c7313ce9a14f664ce5f32d8a79a84
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
/data #

# 搭建成功
172.38.0.14:6379> cluster nodes
f86cd1e9ab3ef69d6c7da52dddc16091346f00d7 172.38.0.12:6379@16379 master - 0 1607142666417 2 connected 5461-10922
9d3e36fdff17d3b5f95e94024d2af63d8c19be32 172.38.0.16:6379@16379 slave f86cd1e9ab3ef69d6c7da52dddc16091346f00d7 0 1607142667421 6 connected
2ceb335c841c7313ce9a14f664ce5f32d8a79a84 172.38.0.13:6379@16379 slave c30fdd6b0698566ed0fc043c267809a98353e5a0 0 1607142667019 7 connected
20ea2a40faaa3212237677d3adefe3fe543fa838 172.38.0.15:6379@16379 slave 0f5cca1448266f1afb8a2818229e73f716ccf3e4 0 1607142666000 5 connected
c30fdd6b0698566ed0fc043c267809a98353e5a0 172.38.0.14:6379@16379 myself,master - 0 1607142666000 7 connected 10923-16383
0f5cca1448266f1afb8a2818229e73f716ccf3e4 172.38.0.11:6379@16379 master - 0 1607142666518 1 connected 0-5460
172.38.0.14:6379>

SpringBoot 微服务打包 Docker 镜像

  1. 编写 SpringBoot 代码
  2. 打包应用
  3. 编写 Dockerfile
  4. 发布镜像到服务器
  5. 发布运行

Docker Compose

轻松高效地管理容器,定义运行多个容器

让程序在任何地方运行:web 服务、redis、mysql、nginx

本节文档:https://docs.docker.com/compose/gettingstarted/

三步骤

1
2
3
4
5
- 1、定义 Dockerfile
- 2、编写 docker-compose.yml
- services:容器,应用(web、redis、mysql)
- project:项目,一组关联的容器
- 3、通过命令 docker-compose up 启动

例子

  1. 编写应用 app.py
  • Create a directory for the project:
1
2
$ mkdir composetest
$ cd composetest
  • 编写应用 app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import time

import redis
from flask import Flask

app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)

def get_hit_count():
retries = 5
while True:
try:
return cache.incr('hits')
except redis.exceptions.ConnectionError as exc:
if retries == 0:
raise exc
retries -= 1
time.sleep(0.5)

@app.route('/')
def hello():
count = get_hit_count()
return 'Hello World! I have been seen {} times.\n'.format(count)
  • 创建 requirements.txt
1
2
flask
redis
  1. 编写 Dockerfile
1
2
3
4
5
6
7
8
9
10
FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
EXPOSE 5000
COPY . .
CMD ["flask", "run"]
  1. 定义docker-compose.yml
1
2
3
4
5
6
7
8
version: "3.8"
services:
web:
build: .
ports:
- "5000:5000"
redis:
image: "redis:alpine"
  1. 启动并访问服务
  • 启动
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ docker-compose up

Creating network "composetest_default" with the default driver
Creating composetest_web_1 ...
Creating composetest_redis_1 ...
Creating composetest_web_1
Creating composetest_redis_1 ... done
Attaching to composetest_web_1, composetest_redis_1
web_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
redis_1 | 1:C 17 Aug 22:11:10.480 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis_1 | 1:C 17 Aug 22:11:10.480 # Redis version=4.0.1, bits=64, commit=00000000, modified=0, pid=1, just started
redis_1 | 1:C 17 Aug 22:11:10.480 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
web_1 | * Restarting with stat
redis_1 | 1:M 17 Aug 22:11:10.483 * Running mode=standalone, port=6379.
redis_1 | 1:M 17 Aug 22:11:10.483 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
web_1 | * Debugger is active!
redis_1 | 1:M 17 Aug 22:11:10.483 # Server initialized
redis_1 | 1:M 17 Aug 22:11:10.483 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
web_1 | * Debugger PIN: 330-787-903
redis_1 | 1:M 17 Aug 22:11:10.483 * Ready to accept connections

5 、停止

1
2
3
4
5
6
7
[root@server1 composetest]# docker-compose down
Stopping composetest_web_1 ... done
Stopping composetest_redis_1 ... done
Removing composetest_web_1 ... done
Removing composetest_redis_1 ... done
Removing network composetest_default
[root@server1 composetest]#

解释

1
2
3
- 默认网卡:文件夹名\_default,这样都在同一网段,可以通过域名访问
- 默认服务名:文件夹名\_服务名\_num (num:副本数量)
- 一般都是集群部署,不会只有一个实例

docker-compose.yml 编写规则

文档地址:https://docs.docker.com/compose/compose-file/

1
2
3
4
5
6
7
8
9
10
11
12
13
# 1、版本
version: ""

# 2、服务
services:
服务1:
xxx
xxx
服务2:
xxx
xxx

# 其他:网络/卷/全局规则

例子:个人博客

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
# 创建目录m y_wordpress
mkdir my_wordpress

# 创建docker-compose.yml
cd my_wordpress
vim docker-compose.yml


version: '3.3'
services:
db:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
wordpress:
depends_on:
- db
image: wordpress:latest
ports:
- "8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress
volumes:
db_data: {}

# 运行
docker-compose up -d

# 访问
aly:8000

容器部署个人微服务

Docker Swarm

集群方式的部署

CI/CD 之 Jenkins


Docker教程
https://polarisink.github.io/20220813/yuque/Docker教程/
作者
Areis
发布于
2022年8月13日
许可协议