Docker
Docker学习
- Docker概述
- Docker安装
- Docker命令
- Docker镜像
- 容器数据卷
- DockerFile
- Docker网络原理
- IDEA整合Docker
- Docker Compose(集群)
- Docker Swarm
- CICD Jenkins流水线
Docker概述
Docker为什么会出现?
一款产品:开饭—上线!两套环境,应用环境,应用配置
开发-----运维。问题?明明在我的电脑上可以运行,怎么你这里就不行呢?版本更新导致服务不可用,对于运维来说,考验就十分大,开发即运维
环境配置是十分麻烦的,每一个机器都要部署环境(集群Redis,ES,Hadoop…) !费时费力
发布一个项目jar(Redis,MySQL,jdk,ES) ,项目能不能带上环境安装打包!
之前在服务器配置一个应用的环境Redis,Mysql,jdk,ES,Hadoop,配置超级麻烦,不能够跨平台。
Windows发布到Linux!环境差别很大
传统的运维:Jar,运维来做部署的事情
现在:开发打包部署上线,一套流程做完!
Docker给以上的问题提出了解决方案!
Docker的思想来自于集装箱,每个箱子都是相互隔离的。Dokcer通过隔离机制,可以将服务器利用到极致
Docker的历史
2010年,几个搞IT的年轻人,就在美国成立了一家公司,dotCloud
做一些pass的云计算服务!LXC有关的容器技术!
他们将自己的技术(容器化技术)命名,就是Docker!
Docker刚刚诞生的时候,没有引起行业的注意 dotCloud,就活不下去
开源,开放源代码
2013年,将Docker开源
Docker越来越多的人发现了Docker的优点!火了,Docker每个月都会更新一个版本!
2014年4月9日,Docker1.0发布
Docker为什么这么火? 十分的轻巧
在容器技术出来之前,我们都是使用虚拟机技术,VMware
虚拟机:在windows中装一个Vmware,通过这个软件我们可以虚拟出来一台或者多台电脑!笨重
虚拟机也是属于虚拟化技术,Docker容器技术,也是一种虚拟化技术!
1
2
3vm:linux centos原生镜像(一个电脑)隔离,需要开发多个虚拟机 Docker:隔离,镜像(最核心的环境 4m,+jdk+mysql),十分的小巧,运行镜像就可以了,小巧。
到现在,所有开发人员都必须要会Docker
聊聊Docker
Docker是基于Go语言开发的,
官网地址
文档地址,Docker的文档是很详细的
Docker镜像中心 ,远程仓库
Docker能干嘛?
之前的虚拟机技术
虚拟机技术缺点:
- 资源占用十分多
- 冗余步骤多
- 启动非常慢
容器化技术
容器化技术不是模拟的一个完整的操作系统
比较Docker和虚拟机技术的不同
- 传统的虚拟机,虚拟出一条硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件
- 容器内的应用是直接运行在宿主机内,容器是没有自己的内核的,也没有虚拟我们的硬件,所以就轻便了
- 每个容器间是互相隔离的,每个容器内都有一个属于自己的文件系统。互不影响
DevOps(开发运维)
更快速的交付和部署
传统:一堆帮助文档,安装程序
Docker:打包镜像发布测试,一键运行
更便捷的升级和扩缩容
使用了Docker之后,我们部署应用就和搭积木一样
项目打包为一个镜像,扩展服务器A,服务器B。
更简单的系统运维
在容器化之后,我们的开发,测试环境都是高度一致的。
更高效的计算资源利用
Docker是内核级别的虚拟化,可以在一个物理机上运行很多的容器实例!服务器的性能可以被压榨到极致
Docker安装
Docker的基本组成
镜像(image)
docker镜像就好比是一个模板,可以通过这个模板来创建容器服务,tomcat镜像====》tomcat容器(提供服务器),
通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器的)
容器(container)
Docker利用容器技术,独立运行一个或者一个组应用,通过镜像来创建的。
启动,停止,删除,基本命令
目前就可以吧这个容器理解为一个简易的linux系统
仓库(repository)
仓库就是存放镜像的地方!
仓库分为共有仓库和私有仓库!
Docker Hub
阿里云。。。都有容器服务器(配置镜像加速)
安装Docker
环境准备
- 需要会一点点linux基础
- CentOS 7
- 使用xshell连接远程服务器进行操作
环境查看
1
2
3
4# 系统内核是3.10以上的 [root@iZwz90og9utae1lg37hyz7Z ~]# uname -r 3.10.0-1062.18.1.el7.x86_64
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18# 系统版本 [root@iZwz90og9utae1lg37hyz7Z ~]# cat /etc/os-release NAME="CentOS Linux" VERSION="7 (Core)" ID="centos" ID_LIKE="rhel fedora" VERSION_ID="7" PRETTY_NAME="CentOS Linux 7 (Core)" ANSI_COLOR="0;31" CPE_NAME="cpe:/o:centos:centos:7" HOME_URL="https://www.centos.org/" BUG_REPORT_URL="https://bugs.centos.org/" CENTOS_MANTISBT_PROJECT="CentOS-7" CENTOS_MANTISBT_PROJECT_VERSION="7" REDHAT_SUPPORT_PRODUCT="centos" REDHAT_SUPPORT_PRODUCT_VERSION="7"
安装
[查看帮助文档]([root@iZwz90og9utae1lg37hyz7Z ~]# cat /etc/os-release NAME=“CentOS Linux” VERSION=“7 (Core)” ID=“centos” ID_LIKE=“rhel fedora” VERSION_ID=“7” PRETTY_NAME=“CentOS Linux 7 (Core)” ANSI_COLOR=“0;31” CPE_NAME=“cpe:/o:centos:centos:7” HOME_URL=“https://www.centos.org/” BUG_REPORT_URL=“https://bugs.centos.org/” CENTOS_MANTISBT_PROJECT=“CentOS-7” CENTOS_MANTISBT_PROJECT_VERSION=“7” REDHAT_SUPPORT_PRODUCT=“centos” REDHAT_SUPPORT_PRODUCT_VERSION=“7”)
明确说明需要centos7以上才支持,首先需要卸载久的版本
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# 1、卸载旧的版本 $ sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine # 2、需要的安装包 $ sudo yum install -y yum-utils # 3、设置镜像的仓库 $ sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo # 默认是从国外的! $ sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 使用阿里云的,十分快 # 更新yum软件包索引 [root@iZwz90og9utae1lg37hyz7Z ~]# yum makecache fast # 4、安装docker引擎 docker-ce 社区版 ee企业版 $ sudo yum install docker-ce docker-ce-cli containerd.io # 5、启动docker $ sudo systemctl start docker # 6、使用 docker version 测试是否安装成功
1
2
3# 7、测试hello-world $ sudo docker run hello-world
1
2
3
4
5# 8、查看一下下载的这个hello world在不在 [root@iZwz90og9utae1lg37hyz7Z ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest bf756fb1ae65 4 months ago 13.3kB
1
2
3
4# 9、卸载docker $ sudo yum remove docker-ce docker-ce-cli containerd.io # 卸载依赖 $ sudo rm -rf /var/lib/docker # 删除资源(docker默认的资源路径)
阿里云镜像加速
1、登入阿里云,找到容器镜像服务
2、找到镜像加速地址
3、配置使用
1
2
3
4
5
6
7
8
9sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://ggb52j62.mirror.aliyuncs.com"] } EOF sudo systemctl daemon-reload sudo systemctl restart docker
回顾HelloWorld流程
run的流程分析图
底层原理
Docker是怎么工作的?
Docker是一个Client-Server 结构的系统,Docker的守护进程进行在主机上,通过Socket从客户端访问!
DockerServer接收到Docker-Client的指令,就会执行这个命令
Docker为什么比VM快
- Docker有比虚拟机更少的抽象层
- Docker利用的是宿主机的内核,VM是需要GuestOS。
所以说,新建一个容器的时候,docker不需要像虚拟机一样重新加载一个操作系统内核,避免引导,虚拟机是加载Guest OS,分钟级别的,
而docker是利用宿主机的操作系统,省略了这个复杂的过程,是秒级别的。
Docker的常用命令
帮助命令
1
2
3
4docker version # 显示docker版本信息 docker info # 显示docker的系统信息,包括镜像和容器的信息 docker 命令 --help # 帮助命令
帮助文档的命令:https://docs.docker.com/reference/
镜像命令
docker images 查看所有本主机的镜像
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15[root@iZwz90og9utae1lg37hyz7Z /]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest bf756fb1ae65 4 months ago 13.3kB # 解释 REPOSITORY 镜像的仓库源 TAG 镜像的版本信息,标签 IMAGE ID 镜像的id CREATED 镜像的创建时间 SIZE 镜像的大小 # 可选项 -a, --all # 列出所有镜像 -q, --quiet # 只显示镜像id
docker search 搜索镜像
1
2
3
4
5
6
7
8
9
10
11
12
13
14[root@iZwz90og9utae1lg37hyz7Z /]# docker search mysql NAME DESCRIPTION STARS OFFICIAL AUTOMATED mysql MySQL is a widely used, open-source relation… 9566 [OK] mariadb MariaDB is a community-developed fork of MyS… 3473 [OK] # 可选项 --filter=STARS=3000 # 过滤收藏数大于3000的 [root@iZwz90og9utae1lg37hyz7Z /]# docker search mysql --filter=STARS=3000 NAME DESCRIPTION STARS OFFICIAL AUTOMATED mysql MySQL is a widely used, open-source relation… 9566 [OK] mariadb MariaDB is a community-developed fork of MyS… 3473 [OK]
**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
37
38
39
40
41
42# 下载镜像 docker pull 镜像名[:tag] [root@iZwz90og9utae1lg37hyz7Z /]# docker pull mysql Using default tag: latest # 如果不写版本,默认下载最新版 latest: Pulling from library/mysql afb6ec6fdc1c: Pull complete # 分层下载:docker image的核心,联合文件系统 0bdc5971ba40: Pull complete 97ae94a2c729: Pull complete f777521d340e: Pull complete 1393ff7fc871: Pull complete a499b89994d9: Pull complete 7ebe8eefbafe: Pull complete 597069368ef1: Pull complete ce39a5501878: Pull complete 7d545bca14bf: Pull complete 211e5bb2ae7b: Pull complete 5914e537c077: Pull complete Digest: sha256:a31a277d8d39450220c722c1302a345c84206e7fd4cdb619e7face046e89031d # 签名 防伪 Status: Downloaded newer image for mysql:latest docker.io/library/mysql:latest # 真实地址 # 其实这两个命令是等价的 docker pull mysql docekr pull docker.io/library/mysql:latest # 指定版本下载 [root@iZwz90og9utae1lg37hyz7Z /]# docker pull mysql:5.7 5.7: Pulling from library/mysql afb6ec6fdc1c: Already exists 0bdc5971ba40: Already exists 97ae94a2c729: Already exists f777521d340e: Already exists 1393ff7fc871: Already exists a499b89994d9: Already exists 7ebe8eefbafe: Already exists 4eec965ae405: Pull complete a531a782d709: Pull complete 270aeddb45e3: Pull complete b25569b61008: Pull complete Digest: sha256:d16d9ef7a4ecb29efcd1ba46d5a82bda3c28bd18c0f1e3b86ba54816211e1ac4 Status: Downloaded newer image for mysql:5.7 docker.io/library/mysql:5.7
docker rmi -f 删除镜像
1
2
3
4[root@iZwz90og9utae1lg37hyz7Z /]# docker rmi -f 镜像id # 删除指定镜像 [root@iZwz90og9utae1lg37hyz7Z /]# docker rmi -f 镜像id 镜像id 镜像id # 删除多个镜像(空格分开) [root@iZwz90og9utae1lg37hyz7Z /]# docker rmi -f $(docker images -qa) #骚操作,采用联合查询删除所有镜像
容器命令
说明:有了镜像才可以创建容器,linux,下载一个centos镜像来测试学习
1
2docker pull centos
新建容器并启动
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23docker run[可选参数] 镜像id #参数说明 --name = "Name" #给容器取个别名 tomcat01 tomcat02 -d #后台方式运行 -it #使用交互方式运行,进入容器查看内容 -p(小写) #指定容器的端口,8080:8080 -p 主机端口:容器端口 (常用) -p 容器端口 -P(大写) #随机指定端口 # 测试,启动并进入容器 [root@iZwz90og9utae1lg37hyz7Z /]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE centos latest 470671670cac 4 months ago 237MB [root@iZwz90og9utae1lg37hyz7Z /]# docker run -it 470671670cac /bin/bash [root@eea5ced1bcb8 /]# ls # 查看容器内容的centos,基础版本很多命令不完善 bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var # 从容器中退回主机 [root@eea5ced1bcb8 /]# exit
列出所有运行中的容器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24# docker ps 命令 #列出当前正在运行的容器 -a #列出当前正在运行的容器+带出历史运行过的容器 -n=? #显示最近创建的容器 -q # 只显示容器的编号 [root@iZwz90og9utae1lg37hyz7Z /]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS [root@iZwz90og9utae1lg37hyz7Z /]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS eea5ced1bcb8 470671670cac "/bin/bash" 5 minutes ago Exited (127) 2 minutes ago 7c6d68fe38bf bf756fb1ae65 "/hello" 29 minutes ago Exited (0) 29 minutes ago 47934e45992d bf756fb1ae65 "/hello" 3 hours ago Exited (0) 3 hours ago [root@iZwz90og9utae1lg37hyz7Z /]# docker ps -a -n=1 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS eea5ced1bcb8 470671670cac "/bin/bash" 9 minutes ago Exited (127) 6 minutes ago [root@iZwz90og9utae1lg37hyz7Z /]# docker ps -aq eea5ced1bcb8 7c6d68fe38bf 47934e45992d
退出容器
1
2
3exit #直接容器停止并退出 Ctrl+P+Q #容器不停止退出
删除容器
1
2
3
4docker rm 容器id #删除指定的容器,不能删除正在运行的容器,如果要强制删除 rm-f docekr rm -f $(docker ps -aq) #删除所有的容器 docker ps -a -q|xargs docker rm #删除所有的容器
启动和停止容器的操作
1
2
3
4
5docker start 容器id #启动容器 docker restart 容器id #重启容器 docker stop 容器id #停止当前正在运行的容器 docker kill 容器id #强制停止当前容器
常用的其他命令
后台启动容器
1
2
3
4
5
6# docker run -d 镜像名 [root@iZwz90og9utae1lg37hyz7Z /]# docker run -d centos # 问题:docker ps ,发现centos停止了?? #常见的坑:docker容器使用后天运行,就必须要有一个前天进程,docker发现没有应用,就会自动停止 #nginx,容器启动后,发现自己没有提供服务,就会立即停止,就是没有程序了
查看日志
1
2
3
4
5docker logs [可选项] -tf # 显示日志 --tail number # 显示日志条数 [root@iZwz90og9utae1lg37hyz7Z /]# docker logs -tf --tail 10 容器id
查看容器中的进程信息 ps
1
2
3
4
5
6#命令 docker top 容器id [root@iZwz90og9utae1lg37hyz7Z ~]# docker top d7f8882680a1 UID PID PPID C STIME TTY TIME root 22262 22245 0 17:40 pts/0 00:00:00
查看镜像的元数据
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
210
211#命令 docker inspect 容器id # 测试 [root@iZwz90og9utae1lg37hyz7Z ~]# docker inspect d7f8882680a1 [ { "Id": "d7f8882680a11fa697b52b00487f927becadff47500d9164be3ef3c5b5151f94", "Created": "2020-05-30T09:40:07.580695306Z", "Path": "/bin/bash", "Args": [], "State": { "Status": "running", "Running": true, "Paused": false, "Restarting": false, "OOMKilled": false, "Dead": false, "Pid": 22262, "ExitCode": 0, "Error": "", "StartedAt": "2020-05-30T09:40:07.935601958Z", "FinishedAt": "0001-01-01T00:00:00Z" }, "Image": "sha256:470671670cac686c7cf0081e0b37da2e9f4f768ddc5f6a26102ccd1c6954c1ee", "ResolvConfPath": "/var/lib/docker/containers/d7f8882680a11fa697b52b00487f927becadff47500d9164be3ef3c5b5151f94/resolv.conf", "HostnamePath": "/var/lib/docker/containers/d7f8882680a11fa697b52b00487f927becadff47500d9164be3ef3c5b5151f94/hostname", "HostsPath": "/var/lib/docker/containers/d7f8882680a11fa697b52b00487f927becadff47500d9164be3ef3c5b5151f94/hosts", "LogPath": "/var/lib/docker/containers/d7f8882680a11fa697b52b00487f927becadff47500d9164be3ef3c5b5151f94/d7f8882680a11fa697b52b00487f927becadff47500d9164be3ef3c5b5151f94-json.log", "Name": "/gallant_austin", "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, "Capabilities": null, "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/ca896847bd3647809cf2bb90a22239e99a33cee8158cfcd958020aebff46b284-init/diff:/var/lib/docker/overlay2/e1d29bc072eab6c1fafe40da590a23718c50eb94cf0dc9b63a6445795d2e2e69/diff", "MergedDir": "/var/lib/docker/overlay2/ca896847bd3647809cf2bb90a22239e99a33cee8158cfcd958020aebff46b284/merged", "UpperDir": "/var/lib/docker/overlay2/ca896847bd3647809cf2bb90a22239e99a33cee8158cfcd958020aebff46b284/diff", "WorkDir": "/var/lib/docker/overlay2/ca896847bd3647809cf2bb90a22239e99a33cee8158cfcd958020aebff46b284/work" }, "Name": "overlay2" }, "Mounts": [], "Config": { "Hostname": "d7f8882680a1", "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", "Volumes": null, "WorkingDir": "", "Entrypoint": null, "OnBuild": null, "Labels": { "org.label-schema.build-date": "20200114", "org.label-schema.license": "GPLv2", "org.label-schema.name": "CentOS Base Image", "org.label-schema.schema-version": "1.0", "org.label-schema.vendor": "CentOS", "org.opencontainers.image.created": "2020-01-14 00:00:00-08:00", "org.opencontainers.image.licenses": "GPL-2.0-only", "org.opencontainers.image.title": "CentOS Base Image", "org.opencontainers.image.vendor": "CentOS" } }, "NetworkSettings": { "Bridge": "", "SandboxID": "3c28f68ab437d44fc52e3132fe473dac6f8c4f217860af2c44164863c6e6b192", "HairpinMode": false, "LinkLocalIPv6Address": "", "LinkLocalIPv6PrefixLen": 0, "Ports": {}, "SandboxKey": "/var/run/docker/netns/3c28f68ab437", "SecondaryIPAddresses": null, "SecondaryIPv6Addresses": null, "EndpointID": "518937c65fb1d275e0dfb828fee65418dda8ddc497a6e0cbc62867474f3b808b", "Gateway": "172.17.0.1", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "IPAddress": "172.17.0.2", "IPPrefixLen": 16, "IPv6Gateway": "", "MacAddress": "02:42:ac:11:00:02", "Networks": { "bridge": { "IPAMConfig": null, "Links": null, "Aliases": null, "NetworkID": "912b291ba3c83933000fd3176a476f87bbbb02aa38d5ef59511f5a2e4fc43e2b", "EndpointID": "518937c65fb1d275e0dfb828fee65418dda8ddc497a6e0cbc62867474f3b808b", "Gateway": "172.17.0.1", "IPAddress": "172.17.0.2", "IPPrefixLen": 16, "IPv6Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "MacAddress": "02:42:ac:11:00:02", "DriverOpts": null } } } } ]
进入当前正在运行的容器(重要常用)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24# 我们通常容器都是使用后台方式运行的,需要进入容器,修改一些配置 # 命令 # 方式一: docker exec -it 容器id bashshell [root@iZwz90og9utae1lg37hyz7Z ~]# docker exec -it d7f8882680a1 /bin/bash # 进入容器后的操作 [root@d7f8882680a1 /]# ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 09:40 pts/0 00:00:00 /bin/bash root 17 0 0 09:53 pts/1 00:00:00 /bin/bash root 30 17 0 09:53 pts/1 00:00:00 ps -ef #方式二: docker attach 容器id #测试 [root@d7f8882680a1 /]# docker attach d7f8882680a1 正在执行当前的代码。。。 # docker exec #进入容器后进入一个新的终端,可以在里面操作 # docker attach #进入容器正在执行的终端,不会启动新的进程
从容器内拷贝文件到主机上
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24docker cp 容器id:容器内路径 目的主机路径 # 测试,将容器内的test.java文件复制到主机的home目录下 # 进入容器内部 [root@iZwz90og9utae1lg37hyz7Z home]# docker attach d7f8882680a1 [root@d7f8882680a1 /]# cd /home # 在容器内部创建一个文件 [root@d7f8882680a1 home]# touch test.java [root@d7f8882680a1 home]# ls test.java # 退出容器 [root@d7f8882680a1 home]# exit exit # 将文件拷贝出来到主机上 [root@iZwz90og9utae1lg37hyz7Z /]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS d7f8882680a1 centos "/bin/bash" 34 minutes ago Exited (127) About a minute ago [root@iZwz90og9utae1lg37hyz7Z /]# docker cp d7f8882680a1:/home/test.java /home [root@iZwz90og9utae1lg37hyz7Z /]# cd home [root@iZwz90og9utae1lg37hyz7Z home]# ls test.java www #问题? 拷贝是手动过程,未来我们使用 -v卷的技术,可以实现自动同步
命令小结
docker的命令是十分多的,特此做个 笔记总结:
体验docker
1、使用Docker安装Nginx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20# 1、搜索镜像 search 建议去docker hub搜索,可以看到帮助文档信息 # 2、下载镜像 pull # 3、启动 [root@iZwz90og9utae1lg37hyz7Z ~]# docker run -d --name myNginx -p 3344:80 nginx # 4、启动成功后,本地测试 [root@iZwz90og9utae1lg37hyz7Z ~]# curl localhost:3344 # http://112.74.167.52:3344/ # 注意:这里可能会有个小问题,如果这里没有正常放回界面,应该是阿里云的安全组那边没有开放端口,进入ECS控制台添加安全组开放端口即可 # 5、进入nginx容器 [root@iZwz90og9utae1lg37hyz7Z ~]# docker exec -it myNginx /bin/bash $测试: [root@iZwz90og9utae1lg37hyz7Z ~]# docker exec -it myNginx /bin/bash # 进入容器了 root@b645aa7b2116:/# whereis nginx nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx root@b645aa7b2116:/# cd /etc/nginx root@b645aa7b2116:/etc/nginx# ls conf.d fastcgi_params koi-utf koi-win mime.types modules nginx.conf scgi_params uwsgi_params win-utf root@b645aa7b2116:/etc/nginx#
端口暴露的概念
思考的问题? 每次改动nginx配置文件,都需要进入容器内??十分麻烦,要是可以在容器外部提供一个映射路径,达到在容器外修改文件,容器内就能自动修改,那就OK, -v数据卷技术可以实现
2、使用docker安装一个tomcat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17# 官方的使用 docker run -it --rm tomcat:9.0 # 我们之前的启动都是后台,停止了容器之后,容器还是可以查到,docker -it --rm ,用完即删除,用来测试用 # 下载启动 [root@iZwz90og9utae1lg37hyz7Z ~]# docker pull tomcat 下载镜像 [root@iZwz90og9utae1lg37hyz7Z ~]# docker run -d -p 3355:8080 --name myTomcat tomcat # 运行 # localhost:3355 报404的错误,这个时候说明外网已经可以访问了 # 进入容器 [root@iZwz90og9utae1lg37hyz7Z ~]# docker exec -it myTomcat /bin/bash root@d03c0c1b5ef3:/usr/local/tomcat# ls BUILDING.txt CONTRIBUTING.md LICENSE NOTICE README.md RELEASE-NOTES RUNNING.txt bin conf lib logs native-jni-lib temp webapps webapps.dist work # 发现问题,webapps目录下面为空,阉割版,所有访问的时候没有内容,阿里云镜像的原因,默认是最小的镜像。保证最小可运行的环境 复制webapps.dist中的内容到webapps目录下即可正常访问
思考:我们以后要部署项目,如果每次都要进入容器的话就很麻烦,要是可以在容器外部提供一个映射路径 ,webapps,在外部放置项目就自动同步到内部就好了!
3、部署ES+kibana
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# es 暴露的端口很多 # es十分耗内存 # es的数据一般需要放置到安全目录!挂载 # --net somenetwork 这个是网络配置 # 启动es 下载安装一步到位 $ docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2 # 启动了 linux就卡住,内存爆炸了 # docker stats 查看cpu状态 # 增加内存限制 -e $ docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2 # 查看内存消耗 CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK 859d68a4564b elasticsearch 0.40% 338.9MiB / 1.795GiB 18.44% 0B / 0B 0B / # 访问测试 [root@pihao ~]# curl localhost:9200 { "name" : "859d68a4564b", "cluster_name" : "docker-cluster", "cluster_uuid" : "67U8HpnDTPS9vqQJEaAkWg", "version" : { "number" : "7.6.2", "build_flavor" : "default", "build_type" : "docker", "build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f", "build_date" : "2020-03-26T06:34:37.794943Z", "build_snapshot" : false, "lucene_version" : "8.4.0", "minimum_wire_compatibility_version" : "6.8.0", "minimum_index_compatibility_version" : "6.0.0-beta1" }, "tagline" : "You Know, for Search" }
使用kibana连接elasticsearch,网络怎么连接呢?
容器内部之间要怎么进行连接呢
可视化
- portainer
- Rancher(CI/CD)
什么是portainer?
Docker图形化界面管理工具,提供一个后台面板供我们操作!
1
2
3docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
访问测试:http://112.74.167.52:8088/
选择本地:
可视化面板,平时用的不多!
Docker镜像讲解
镜像是什么
所有的应用,直接打包docker镜像,就可以直接跑起来,包括代码、库、环境变量和皮遏制文件;
如何得到镜像:
-
从远程仓库下载
-
朋友拷贝
-
自己制作一个镜像DockerFile
Docker镜像加载原理
UnionFS (联合文件系统)
docker的镜像实际上由一层一层的文件系统组成,这种从层级的文件系统UnionFS
分层理解
所有的docker镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。
特点
Docker镜像都是只读的,当容器启动时,一个新的可写层被加载镜像的顶部!
这一层就是我们通常说的容器层,容器之下的都叫镜像层!
如何提交一个自己的镜像??
commit镜像
1
2
3
4docker commit 提交容器成为一个新的副本 # 命令和git原理类似 docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[TAG]
实战观测:
官网提供的tomcat镜像的webapps目录是空的,那我们就做一个webapps目录下面有文件的,然后发布
1
2
3
4
5
6
7
8
9
10# 启动一个默认的tomcat # 发现这个默认的tomcat是没有webapps应用 # 我自己进去拷贝了基本的文件 # 将我们操作过的容器通过commit提交作为一个镜像,我们以后就使用这个修改过的镜像即可,这就我我们自己的一个修改过的镜像,结合maven的 mvn install理解 [root@pihao ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS f44a55d3dd55 tomcat "catalina.sh run" 7 minutes ago Up 7 minutes 0.0.0.0:8080->8080/tcp [root@pihao ~]# docker commit -a="pihao" -m="add webapps application" f44a55d3dd55 tomcat_pihao:1.0
通过实操至此,差不多算是入门docker了!!!! 继续加油~~~
容器数据卷
什么是容器数据卷
docker理念
将应用和环境打包成一个镜像!
数据?如果数据都在容器中,那么我们容器删除,数据也会丢失,需求:数据可以持久化
Mysql,容器删了,那就是删库跑路了,需求:Mysql数据可以存储在本地。
容器之间可以有一个数据共享的技术!docker容器中产生的数据,同步到本地
这就是数据卷技术,目录的挂载,将我们容器内的目录,挂载到Linux上面。
总结:容器的持久化和同步操作!容器间也是可以数据共享的
使用数据卷
方式一:直接使用命令来挂载 -v
1
2[root@pihao ~]# docker run -it -v 主机目录:容器内目录 镜像id
1
2
3
4
5
6# 测试: [root@pihao home]# docker run -it -v /home/ceshi:/home centos /bin/bash # 启动起来之后我们通过docker inspect 容器id 查看元数据 [root@pihao home]# docker inspect 6a08f0d81c50
1
2
3
4
5
6
7
8
9
10
11
12
13"Mounts": [ 挂载 -v 卷 { "Type": "bind", "Source": "/home/ceshi", 主机内地址 "Destination": "/home", docker容器内地址 "Mode": "", "RW": true, "Propagation": "rprivate" } ], #同步测试
继续测试:
- 停止容器
- 在宿主机上修改文件
- 启动容器
- 容器内的数据依旧是同步的
好处:我们以后修改只需要在本地修改即可,容器会自动同步过去!
实战:Mysql数据同步
思考:Mysql的数据持久化问题!
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# 获取镜像 [root@pihao ~]# docker pull mysql:5.7 # 安装启动mysql,需要配置密码的,这是要注意点 $ docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag # 官方提供的设置密码命令 # 运行镜像,做数据挂载 [root@pihao ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE tomcat_pihao 1.0 8512e11068c0 12 hours ago 652MB portainer/portainer latest 1ec116aed60c 46 hours ago 79.1MB mysql 5.7 a4fdfd462add 9 days ago 448MB tomcat 9.0 1b6b1fe7261e 2 weeks ago 647MB tomcat latest 1b6b1fe7261e 2 weeks ago 647MB nginx latest 9beeba249f3e 2 weeks ago 127MB elasticsearch 7.6.2 f29a1ee41030 2 months ago 791MB centos latest 470671670cac 4 months ago 237MB # 可以做多个数据挂载 : /etc/mysql/conf.d(这个是mysql的配置文件目录) /var/lib/mysql(这个是mysql的数据库目录) -d 后台运行 -d 端口映射 -v 卷挂载 -e 环境配置 --name 取别名 # 启动第一个mysql [root@pihao ~]# 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 # 启动成功之后使用本地的连接工具Navicat测试连接mysql # Navicat连接到服务器的3310,------3310和容器内的3306做了映射,这个时候就能连上了 # 在本地测试创建一个数据库,查看一下映射路径是否也创建了
假设将容器删除,发现我们挂载到本地的数据卷依旧没有丢失,这就实现了容器数据的持久化功能!
具名和匿名挂载
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# 匿名挂载 -v 容器内路径 (不写主机的路径) docker run -d -P --name nginx01 -v /etc/nginx nginx # 查看所有的volume情况 [root@pihao data]# docker volume ls DRIVER VOLUME NAME local 0bd6ec25d165dfd5e55ec8d7376a619f720e71c94b062fef5bcd9d643890202f local 5352b1b1d189180f75ae95a4aba702af3eab6dbf22c7196ee0b73491ca78ae39 # 这里发现,这就是匿名挂载,因为我们在-v的时候只写了容器内的路径,而没有取名字 # 具名挂载 # 再开一个nginx 这时给容器内的路径取一个名字:juming [root@pihao /]# docker run -d -P -v juming:/etc/nginx --name nginx02 nginx 20bfd4124e5fadaf25a9dce86dfb8d216ade483db25e1d767b144f695b2c74ab [root@pihao /]# docker volume ls DRIVER VOLUME NAME local juming # 取的名字 # 通过-v 卷名:容器内路径 # 查看卷的信息 docker volume inspect 卷名 [root@pihao /]# docker volume inspect juming [ { "CreatedAt": "2020-05-31T10:53:25+08:00", "Driver": "local", "Labels": null, "Mountpoint": "/var/lib/docker/volumes/juming/_data", "Name": "juming", "Options": null, "Scope": "local" } ]
所有的docker容器内的卷,没有指定目录的情况下都是在: /var/lib/docker/volumes/xxxx/_data
我们通过具名挂载,可以方便的找到我们的一个卷,大多数情况下载使用的 具名挂载
1
2
3
4
5# 如何确实是具名挂载还是匿名挂载??还是指定路径挂载 -v 容器内路径 #匿名挂载 -v 卷名:容器内路径 #具名挂载 -v /宿主机路径:容器内路径 #指定路径挂载
拓展:
1
2
3
4
5
6
7
8
9# 通过 -v 容器内路径:ro rw 改变读写权限 # ro read only 只读 # rw read and write 可读可写 # 一旦设置了容器权限,容器对我们挂载出来的内容就有限定了 [root@pihao /]# docker run -d -P -v juming:/etc/nginx:ro --name nginx01 nginx [root@pihao /]# docker run -d -P -v juming:/etc/nginx:rw --name nginx02 nginx # ro 只要看到ro就说明这个路径只能通过宿主机来操作,容器内部是无法操作的
初识DockerFile
DockerFile就是用来构建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# 创建一个dockerfile文件,名字可以随便取,建议dockerfile01 # 文件中的内容 指令(大写) 参数 FROM centos VOLUME ["volume01","volume02"] # 这里其实是匿名挂载,在容器外部必定会生成一个目录与它同步 CMD echo "------end------" CMD bin/bash #这里每个命令都是镜像的一层 # 将命令打包 [root@pihao docker_volume_test]# docker build -f dockerfile01 -t pihao/centos:1.0 . Sending build context to Docker daemon 2.048kB Step 1/4 : FROM centos ---> 470671670cac Step 2/4 : VOLUME ["volume01","volume02"] ---> Running in ce323b96416b Removing intermediate container ce323b96416b ---> d8f8fdc5edd8 Step 3/4 : CMD echo "------end------" ---> Running in cedae7372d3a Removing intermediate container cedae7372d3a ---> 136048f7f683 Step 4/4 : CMD bin/bash ---> Running in d381121bac22 Removing intermediate container d381121bac22 ---> 9f36ff977d42 Successfully built 9f36ff977d42 Successfully tagged pihao/centos:1.0 [root@pihao docker_volume_test]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE pihao/centos 1.0 9f36ff977d42 14 seconds ago 237MB # 打包好的镜像
1
2
3
4
5
6
7
8
9
10
11
12# 启动一下自己生成的容器 [root@pihao docker_volume_test]# docker run -it 9f36ff977d42 /bin/bash [root@0f1d1bf75b84 /]# ls -l drwxr-xr-x 2 root root 4096 May 11 2019 srv dr-xr-xr-x 13 root root 0 May 31 04:31 sys drwxrwxrwt 7 root root 4096 Jan 13 21:49 tmp drwxr-xr-x 12 root root 4096 Jan 13 21:49 usr drwxr-xr-x 20 root root 4096 Jan 13 21:49 var drwxr-xr-x 2 root root 4096 May 31 04:31 volume01 # 这两个目录就是我们生成镜像的时候自动挂载的,数据卷目录 drwxr-xr-x 2 root root 4096 May 31 04:31 volume02
这个卷:volume01,volume02 在外部一定有一个与它同步的目录!
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# 使用inspect命令查看一下这个容器的卷挂载路径 [root@pihao ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS 48bbedc992a3 9f36ff977d42 "/bin/bash" 41 minutes ago Up 41 minutes [root@pihao ~]# docker inspect 48bbedc992a3 "Mounts": [ { "Type": "volume", "Name": "56e6675052e05ea4a9b08eb72ca9bd776627c6e360a6b4ffbd205519cc82eff2", "Source": "/var/lib/docker/volumes/56e6675052e05ea4a9b08eb72ca9bd776627c6e360a6b4ffbd205519cc82eff2/_data", "Destination": "volume01", "Driver": "local", "Mode": "", "RW": true, "Propagation": "" }, { "Type": "volume", "Name": "670c6b43a2af71397c18a85e92b393745eb9bf0b1318e5dd0529a6c39eacba83", "Source": "/var/lib/docker/volumes/670c6b43a2af71397c18a85e92b393745eb9bf0b1318e5dd0529a6c39eacba83/_data", "Destination": "volume02", "Driver": "local", "Mode": "", "RW": true, "Propagation": "" } ] # 发现 volume01 和volume02 挂载的同步文件在主机的 /var/lib/docker/volumes/xxxx/_date目录下
查看同步情况:
在容器内的volume01下创建一个container.txt文件
然后在volume01文件对应的主机同步目录中查看是否已经同步完成:
这种方式在以后的工作中经常使用,因为我们通常会构建自己的镜像!
假设构建镜像的时候没有挂载卷,就要手动镜像挂载 -v 卷名:容器内路径!
数据卷容器
场景:多个mysql同步数据,容器与容器之间信息交互
1
2# 启动3个容器,通过我们自己写的镜像启动
启动pihao/centos:1.0 ,取名为docker01
启动pihao/centos:1.0 ,取名为docker02 --volumes-from docker01
现在要做的操作:
在docker01的volume01中新建一个文件夹docker01,看看会不会同步的到docker02的volume01中
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# 进入容器docker01 新建文件夹docker01 [root@pihao docker_volume_test]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 4b8f6d78b9ea pihao/centos:1.0 "/bin/sh -c bin/bash" 7 minutes ago Up 7 minutes docker02 9dda52409402 pihao/centos:1.0 "/bin/sh -c bin/bash" 14 minutes ago Up 14 minutes docker01 [root@pihao docker_volume_test]# docker attach 9dda52409402 [root@9dda52409402 /]# ls opt proc root run sbin srv sys tmp usr var volume01 volume02 [root@9dda52409402 /]# cd volume01 [root@9dda52409402 volume01]# mkdir docker01 [root@9dda52409402 volume01]# ls docker01 # 进入容器docker02,查看文件是否被同步过来 [root@pihao ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS 4b8f6d78b9ea pihao/centos:1.0 "/bin/sh -c bin/bash" 12 minutes ago Up 12 minutes docker02 9dda52409402 pihao/centos:1.0 "/bin/sh -c bin/bash" 19 minutes ago Up 19 minutes docker01 [root@pihao ~]# docker attach 4b8f6d78b9ea [root@4b8f6d78b9ea /]# ls opt proc root run sbin srv sys tmp usr var volume01 volume02 [root@4b8f6d78b9ea /]# cd volume01 [root@4b8f6d78b9ea volume01]# ls docker01 # 发现已经被同步过来(docker01创建的数据同步到了docker02上)
启动pihao/centos:1.0 ,取名为docker03 -volumes–from docker01
1
2
3
4
5
6
7
8
9
10
11# 进入docker01,检查文件是否同步过来 [root@pihao ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c5c69147c3e0 pihao/centos:1.0 "/bin/sh -c bin/bash" 3 minutes ago Up 3 minutes docker03 4b8f6d78b9ea pihao/centos:1.0 "/bin/sh -c bin/bash" 25 minutes ago Up 25 minutes docker02 9dda52409402 pihao/centos:1.0 "/bin/sh -c bin/bash" 32 minutes ago Up 32 minutes docker01 [root@pihao ~]# docker attach 9dda52409402 [root@9dda52409402 volume01]# ls docker01 docker03 # 发现docker03已经同步过来了
1
2
3# 测试 可以删除docker01,查看一下docker02和docker03是否还可以访问volume01这个文件夹 # 发现依旧存在
多个mysql实现数据共享
1
2
3
4
5
6
7
8# mysql01 [root@pihao ~]# docker run -d -p 3310:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7 # mysql02 [root@pihao ~]# docker run -d -p 3311:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7 # 这个时候,就可以实现两个容器数据同步
1
2
3
4结论: 容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止 但是一旦持久化到了本地,本地的数据是不会删除的
DockerFile
DockerFile介绍
dockerfile 是用来构建docker镜像的文件,!命令参数脚本
构建步骤
- 编写一个dockerfile文件
- docker build 构建一个镜像
- docker run 运行镜像
- docker push 发布镜像(DockerHub阿里云镜像仓库)
看看官方是怎么做的??DockerHub上随便搜一个镜像
发现跳转到github,发现也是一组命令构成
官方既然可以制作镜像,我们也可以!!!
DockerFile构建过程
基础知识:
- 每个保留关键字(指令)都必须是大写字母
- 执行从上到下顺序执行
- #表示注释
- 每个指令都是创建提交一个新的镜像层,并提交!
dockerfile是面向开发的,我们以后要发布项目,做镜像,就需要编写dockerfile文件,这个文件十分简单
简单地说,之前将你写的代码打包生成war包或者jar包,现在呢?公司要求将你的代码打包生成docker镜像
Docker镜像逐渐成为企业交付的标准,必须要掌握~~~~
步骤:开发,部署,。。。缺一不可
-
DokcerFile: 构建文件,定义了一切的步骤,源代码
-
DockerImages: 通过DockerFile构建生成的镜像,最终发布和运行的产品,原来是jar,war
-
Docker容器: 容器就是镜像运行起来提供服务的
DockerFile的指令
以前的话我们就是使用别人的,现在我们知道这些指令后,我们来练习自己写一个镜像!
1
2
3
4
5
6
7
8
9
10
11
12
13FROM # 基础镜像,就是一切从这里构建 centos MAINTAINER # 镜像是谁写的,姓名+邮箱 RUN # 镜像构建的时候需要运行的命令 ADD # 步骤,tomcat镜像,这个tomcat压缩包就是添加的内容 WORKDIR # 镜像的工作目录 VOLUME # 挂载的目录位置 EXPOSE # 暴露端口配置 -p CMD # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代 ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令 ONBUILD # 当构建一个被继承DockerFil,这个时候就会触发onbuild的指令 COPY # 类似ADD命令,将我们文件拷贝到镜像中 ENV #构建的时候设置环境变量! 比如说设置内存大小,mysql的密码
实战测试:构建自己的centos
Docker Hub中,百分之九九的镜像都是从这个基础镜像过来的 FROM scratch,然后配置需要的软件和配置来进行构建
创建一个自己的centos
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# 1、编写dockerfile的配置文件(我在home目录下编写一个了mydockerfile-centos的文件,内容如下) FROM centos MAINTAINER pihao<827699764@qq.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 # 2、再通过这个文件构建镜像 # 命令 docker build -f dockerfile文件路径 -t 镜像名字:【TAG】 [root@pihao dockerfile]# docker build -f mydockerfile-centos -t mycentos:1.0 . # 执行结果: Successfully built 844b891d4781 Successfully tagged mycentos:1.0 # 3、测试运行
对比:之前的centos
我们增加之后的镜像
查看镜像历史变更:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20# 我们可以列出本地进行的变更历史 docker history 镜像id [root@pihao dockerfile]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE mycentos 1.0 844b891d4781 15 minutes ago 321MB centos latest 470671670cac 4 months ago 237MB [root@pihao dockerfile]# docker history mycentos:1.0 IMAGE CREATED CREATED BY SIZE COMMENT 844b891d4781 15 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "/bin… 0B cc7835c68b84 15 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B 617d78fe4151 15 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B fbfd40657f5c 15 minutes ago /bin/sh -c #(nop) EXPOSE 80 0B 6ce2a8dca855 15 minutes ago /bin/sh -c yum -y install net-tools 24MB 3639c1768f75 15 minutes ago /bin/sh -c yum -y install vim 59.8MB 301d6576cf44 15 minutes ago /bin/sh -c #(nop) WORKDIR /usr/local 0B f7cd9d68bb8d 15 minutes ago /bin/sh -c #(nop) ENV MYPATH=/usr/local 0B 3c2904681fb0 15 minutes ago /bin/sh -c #(nop) MAINTAINER pihao<82769976… 0B 470671670cac 4 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B <missing> 4 months ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B <missing> 4 months ago /bin/sh -c #(nop) ADD file:aa54047c80ba30064… 237MB
我们平时拿到一个镜像,可以研究一下它是怎么做的??
CMD 和 ENTRYPOINT的区别
测试CMD
1
2
3
4
5# dockerfile FROM centos CMD ["ls","-a"] # 这个命令非常简单,及时启动这个容器的时候执行 ls -a 这个命令
1
2
3# 构建容器 [root@pihao dockerfile]# docker build -f dockerfile-cmd-test -t cmdtest:1.0 .
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# 运行容器,发现 li -a 生效 [root@pihao dockerfile]# docker run cmdtest:1.0 . .. .dockerenv bin dev etc home lib lib64 [root@pihao dockerfile]# # 想追加一个命令 -l 期待效果如: ls -al [root@pihao dockerfile]# docker run cmdtest:1.0 -l docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: "-l": executable file not found in $PATH": unknown. # 发现有问题,因为在cmd的清理下, -l替换了CMD["ls","-a"]的命令,-l不是命令,所以报错 # 命令换成 ls -al即可 [root@pihao dockerfile]# docker run cmdtest:1.0 ls -al total 56 drwxr-xr-x 1 root root 4096 May 31 11:29 . drwxr-xr-x 1 root root 4096 May 31 11:29 .. -rwxr-xr-x 1 root root 0 May 31 11:29 .dockerenv lrwxrwxrwx 1 root root 7 May 11 2019 bin -> usr/bin drwxr-xr-x 5 root root 340 May 31 11:29 dev drwxr-xr-x 1 root root 4096 May 31 11:29 etc drwxr-xr-x 2 root root 4096 May 11 2019 home
测试ENTRYPOINT
1
2
3
4# dockerfile FROM centos ENTRYPOINT ["ls","-a"]
1
2
3
4# 构建容器 [root@pihao dockerfile]# docker build -f dockerfile-entrypoint-test -t entrypoint-test:1.0 .
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# 运行容器,发现 li -a 生效 [root@pihao dockerfile]# docker run entrypoint-test:1.0 . .. .dockerenv bin dev etc home lib lib64 # 想追加一个命令 -l 期待效果如: ls -al [root@pihao dockerfile]# docker run entrypoint-test:1.0 -l total 56 drwxr-xr-x 1 root root 4096 May 31 11:42 . drwxr-xr-x 1 root root 4096 May 31 11:42 .. -rwxr-xr-x 1 root root 0 May 31 11:42 .dockerenv lrwxrwxrwx 1 root root 7 May 11 2019 bin -> usr/bin drwxr-xr-x 5 root root 340 May 31 11:42 dev drwxr-xr-x 1 root root 4096 May 31 11:42 etc drwxr-xr-x 2 root root 4096 May 11 2019 home # 运行成功 # 发现这里的 -l 直接追加到了ENTRYPOINT ["ls","-a"]中
DockerFile中很多命令都十分相似,需要了解他们的区别,最好就是通过对比的方式来学习
实战:Tomcat镜像
1、准备镜像文件tomcat压缩包,jdk的压缩包
1
2
3
4
5[root@pihao tomcat]# ls -l -rw-r--r-- 1 root root 9722154 May 31 20:00 apache-tomcat-8.5.45.tar.gz -rw-r--r-- 1 root root 180362463 May 31 19:56 jdk-11.0.4_linux-x64_bin.tar.gz -rw-r--r-- 1 root root 0 May 31 20:17 readme.txt # readme.txt 空文件
2、编写dockerfile文件,官方命名 Dockerfile ,build会自动寻找这个文件,就不需要 -f 指定了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22FROM centos MAINTAINER pihao<827699764@qq.com> COPY readme.txt /usr/local/readme.txt ADD jdk-11.0.4_linux-x64_bin.tar.gz /usr/local/ ADD apache-tomcat-8.5.45.tar.gz /usr/local/ RUN yum -y install vim ENV MYPATH /usr/local/ WORKDIR $MYPATH ENV JAVA_HOME /usr/local/jdk-11.0.4 ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.45 ENV CATALINA_BASE /usr/local/apache-tomcat-8.5.45 ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin # 这里注意,linux的path环境变量是【冒号:】分隔的 EXPOSE 8080 CMD /usr/local/apache-tomcat-8.5.45/bin/startup.sh && tail -F /usr/local/apache-tomcat-8.5.45/logs/catalina.out
3、构建镜像
1
2
3
4
5
6
7
8[root@pihao tomcat]# docker build -t diytomcat . # 注意:这里的-f不用写,因为先前的dockerfile的名字就是Dockerfile . . . Successfully built 31d4a6fa8956 Successfully tagged diytomcat:latest # 构建成功
4、启动这个容器
1
2
3
4
5
6[root@pihao tomcat]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE diytomcat latest 31d4a6fa8956 6 minutes ago 614MB # 说明 -v 这里挂载了webapps目录 和 logs目录 [root@pihao tomcat]# docker run -d -p 9090:8080 --name pihao-diy-tomcat -v /home/tomcat/test:/usr/local/apache-tomcat-8.5.45/webapps/test -v /home/tomcat/logs:/usr/local/apache-tomcat-8.5.45/logs diytomcat
5、访问测试
6、发布项目(由于做了卷挂载,我们直接在本地发布项目)
1
2
3
4
5
6
7# 切换到主机的/tomcat/test目录,创建WEB-INF目录 [root@pihao test]# mkdir WEB-INF [root@pihao test]# ls WEB-INF [root@pihao WEB-INF]# ls index.jsp web.xml
web.xml
1
2
3
4
5
6
7
8
9<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> </web-app>
index.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>菜鸟教程(runoob.com)</title> </head> <body> Hello World!<br/> <% out.println("你的 IP 地址 " + request.getRemoteAddr()); %> </body> </html>
访问地址:主机ip:9090/test,项目部署成功,可以直接访问ok
我们以后开发的步骤,需要掌握Dockerfile的编写,我们之后的一切都是使用docker镜像来发布运行!
发布自己的镜像到DockerHub
1
2DockerHUb
- 地址:https://hub.docker.com/ 注册自己的账号
- 确定这个账号可以登入
- 在服务器上提交自己的镜像
1
2
3
4
5
6
7
8
9
10
11
12[root@pihao ~]# docker login --help Usage: docker login [OPTIONS] [SERVER] Log in to a Docker registry. If no server is specified, the default is defined by the daemon. Options: -p, --password string Password --password-stdin Take the password from stdin -u, --username string Username
- 登入完毕后就可以提交镜像了,就是一步 docker push
1
2
3
4
5
6
7
8
9
10[root@pihao ~]# docker login -u pihao 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 # 登入成功 [root@pihao ~]#
1
2
3
4
5
6
7
8
9
10
11
12
13[root@pihao ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE truevoly/oracle-12c latest 21789d4d876f 16 months ago 5.7GB jaspeen/oracle-11g latest 0c8711fe4f0f 4 years ago 281MB [root@pihao ~]# docker push jaspeen/oracle-11g The push refers to repository [docker.io/jaspeen/oracle-11g] 5f70bf18a086: Preparing 7a080c2f6e4d: Layer already exists 59af826791e8: Layer already exists 69264aa86d7e: Layer already exists denied: requested access to the resource is denied # 发现给拒绝了,因为这里是根据名字上传到仓库,而这里的是jaspeen账号,那肯定没有权限 [root@pihao ~]# 所以要把这个名字改成自己账号的名字,可以使用docker tag 命令
docker tag 修改镜像名字
发布自己的镜像到阿里云服务器上
-
1、登入阿里云
-
2、找到容器镜像服务
-
3、创建命名空间
- 4、创建容器镜像
- 5、浏览阿里云页面信息
-
6、push到阿里云仓库
复制代码1
2
3
4
5
6
7
8
9
10
11
12
13
14# 退出之前的账号 [root@pihao ~]# docker logout Removing login credentials for https://index.docker.io/v1/ # 登入阿里云的账号 [root@pihao ~]# docker login --username=决魂耗子 registry.cn-shenzhen.aliyuncs.com # 密码是开通阿里云镜像服务时的那个密码 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 [root@pihao ~]#
复制代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22[root@pihao ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE truevoly/oracle-12c latest 21789d4d876f 16 months ago 5.7GB jaspeen/oracle-11g latest 0c8711fe4f0f 4 years ago 281MB pihao/oracle-11g latest 0c8711fe4f0f 4 years ago 281MB # 按照阿里云页面提示修改镜像的 tag [root@pihao ~]# docker tag jaspeen/oracle-11g registry.cn-shenzhen.aliyuncs.com/docker-pihao-01/pihao-test:1.0 [root@pihao ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE truevoly/oracle-12c latest 21789d4d876f 16 months ago jaspeen/oracle-11g latest 0c8711fe4f0f 4 years ago pihao/oracle-11g latest 0c8711fe4f0f 4 years ago registry.cn-shenzhen.aliyuncs.com/docker-pihao-01/pihao-test 1.0 0c8711fe4f0f 4 years ago # 提交,ok [root@pihao ~]# docker push registry.cn-shenzhen.aliyuncs.com/docker-pihao-01/pihao-test The push refers to repository [registry.cn-shenzhen.aliyuncs.com/docker-pihao-01/pihao-test] 5f70bf18a086: Pushed 7a080c2f6e4d: Pushing [==> ] 4.903MB/108.7MB 59af826791e8: Pushed 69264aa86d7e: Pushing [=> ] 5.404MB/172.3MB
阿里云镜像的就参考官网文档即可
小结
Docker网络
理解Docker0
请求所有环境做测试
三个网络
1
2# 问题:docker 是如何处理容器网络访问的,比如容器内的tomcat怎么连接mysql呢??
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21[root@pihao ~]# docker run -d tomcat -P --name tomcat01 tomcat # 查看容器的内部网络地址 ip addr 发现容器启动的时候会得到一个 eth0@if79 的ip地址,这时docker分配的 [root@pihao ~]# docker exec -it tomcat01 ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 78: eth0@if79: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0 valid_lft forever preferred_lft forever [root@pihao ~]# # 思考,linux能不能ping同容器内部! [root@pihao ~]# ping 172.17.0.2 PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data. 64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.094 ms 64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.081 ms # linux可以ping通docker容器内部
原理
1、我们每启动一个docker容器,docker就会给容器分配一个ip,我们只要安装了Docker,就会有一个网卡docker0
桥接模式,我们使用的技术是veth-pair技术
再次测试 ip addr,(启动了一个tomcat01容器之后),发现多了一个网络 79: vetha37f3dc@if78(跟容器内的那个地址类似)
2、再启动一个容器测试,发现又多了一对网卡!
1
2
3
4# 而且还发现这些容器带来的网卡都是一对一对的 # veth-pair技术就是一对的虚拟设备接口,他们都是成对出现的,一端连着协议,一端彼此相连 # 正因为有这个特性,veth-pair 充当一个侨联,连接各种虚拟网络设备
3、我们现在在Docker中启动了tomcat01,tomcat02两个容器,而这两个容器之间是互相独立的,那么他们之间能够ping通嘛?
1
2
3
4
5
6
7# tomcat02 的ip是 172.17.0.2 [root@pihao ~]# docker exec -it tomcat02 ping 172.17.0.2 PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data. 64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.139 ms 64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.096 ms # 结论: 容器和容器之间是可以Ping 通的,因为都是在同一个网段下 docker0 172.17.0.1
绘制一个网络连接模型图:
结论:tomcat01 和tomcat02是共用的一个路由器,docker01
所有的容器不指定网络的情况下,都是由Docker0来路由的,docker会给每个容器分配一个可用 IP
255.255.0.1/16 可以存25535个地址
255.255.0.1/24 可以存255个地址
小结
Docker使用的是Linxux桥接,宿主机中是一个Docker容器的网桥 docker0
Docker中的所有的网络接口都是虚拟的。虚拟的转发效率高。(内网传递文件,速度非常快 10m 10 m的)
只要容器删除,对应的网桥一对也就删除了!
思考一个场景,我们编写了一个微服务,database url = ip:xxxxxx,而我们每次启动容器的时候ip会变化,能不能通过某种技术,我们直接来ping 通容器的名字,作用效果就像SpringCloud中的feign,通过微服务的名字就能实现远程调用。高可用
–link
不用通过网络,直接通过容器的名字来访问
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23[root@pihao ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d4c7d8ebced2 tomcat "catalina.sh run" 45 minutes ago Up 45 minutes 0.0.0.0:32769->8080/tcp tomcat02 081e1f8db911 tomcat "catalina.sh run" 59 minutes ago Up 59 minutes 0.0.0.0:32768->8080/tcp tomcat01 # 想直接通过容器名字来访问,发现行不通 [root@pihao ~]# docker exec -it tomcat02 ping tomcat01 ping: tomcat01: Name or service not known # 如何解决呢?? # 在启动一个tomcat03 启动是使用 --link 命令指定要连接的容器tomcat02 [root@pihao ~]# docker run -d -P --name tomcat03 --link tomcat02 tomcat 9ec98d9557a1f2424212eda8e036883006cc970ab09daa84391c05e3ec70f2d3 # 通过--link,就可以直接使用容器名字访问 [root@pihao ~]# docker exec -it tomcat03 ping tomcat02 PING tomcat02 (172.17.0.3) 56(84) bytes of data. 64 bytes from tomcat02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.135 ms 64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.103 ms # 缺陷,反向可以ping通嘛?? [root@pihao ~]# docker exec -it tomcat02 ping tomcat03 ping: tomcat03: Name or service not known [root@pihao ~]# 发现反向连接就不行
探究 :inspect
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[root@pihao ~]# docker network ls NETWORK ID NAME DRIVER SCOPE e12a90f69e50 bridge bridge local 7514a428f3d0 host host local f1f4981f4fbb none null local [root@pihao ~]# docker network inspect e12a90f69e50 [ { "Name": "bridge", "Id": "e12a90f69e507dae3504769ee12399ec18e427de2d29b675cbf593e4b01f371c", "Created": "2020-06-01T09:17:54.742162379+08:00", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": null, "Config": [ { # docker0的信息 "Subnet": "172.17.0.0/16", # 255*255 "Gateway": "172.17.0.1" # 路由 } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": { # 容器内的信息 "081e1f8db911bcca7288c0ed3eee687c36a290c0f9b9f5e523a8099389342c91": { "Name": "tomcat01", "EndpointID": "c9b47b00655cb11db1735d74ce346ada99b79ad9f399c7686ca944f145a018d1", "MacAddress": "02:42:ac:11:00:02", "IPv4Address": "172.17.0.2/16", "IPv6Address": "" }, "9ec98d9557a1f2424212eda8e036883006cc970ab09daa84391c05e3ec70f2d3": { "Name": "tomcat03", "EndpointID": "e1bf65587d0ae28997b46dc2ffe49fc9ea89f27ac072e34b62573440da6ca66f", "MacAddress": "02:42:ac:11:00:04", "IPv4Address": "172.17.0.4/16", "IPv6Address": "" }, "d4c7d8ebced2387ece1ea16052d3d38c085434552ab9141c171531402295c69c": { "Name": "tomcat02", "EndpointID": "5bd840c78f1a6da803ef55c2086f3961db45a897309e30aff1be1d77d01dcd0e", "MacAddress": "02:42:ac:11:00:03", "IPv4Address": "172.17.0.3/16", "IPv6Address": "" } }, "Options": { "com.docker.network.bridge.default_bridge": "true", "com.docker.network.bridge.enable_icc": "true", "com.docker.network.bridge.enable_ip_masquerade": "true", "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0", "com.docker.network.bridge.name": "docker0", "com.docker.network.driver.mtu": "1500" }, "Labels": {} } ] [root@pihao ~]#
1
2docker inpect tomcat03(使用了--kink连接 tomcat02 ),查看如下图,有一个Links
1
2还有一种方式查看它的连接配置,就是进入容器内容,查看它的映射路径,看看是不是用容器的名字来映射对应的地址 比如:tomcat02: 172.17.0.3
1
2
3
4
5
6
7[root@pihao ~]# docker exec -it tomcat03 cat /etc/hosts 127.0.0.1 localhost 172.17.0.3 tomcat02 d4c7d8ebced2 # 找到了,在这里,不知可以使用容器的名字,还能使用容器id来访问 172.17.0.4 9ec98d9557a1 [root@pihao ~]#
再来查看一下tomcat02的配置
1
2
3
4
5[root@pihao ~]# docker exec -it tomcat02 cat /etc/hosts 127.0.0.1 localhost 172.17.0.3 d4c7d8ebced2 [root@pihao ~]# 发现这里并没有配置tomcat03的路径,那就不能通过tomcat03来访问了,那就再次使用 -- link了
本质探究: --link就是我们在hosts配置中增加了一个172.17.0.3 tomcat02 d4c7d8ebced2
其实我们在使用Docker 已经不建议使用 --link了!!
我们要自定义网络,不使用默认的Docker0网络
Docker0的问题:他不支持容器名连接访问
自定义网络
1
2
3
4
5
6
7
8# 查看所有的docker 网络 [root@pihao ~]# docker network ls NETWORK ID NAME DRIVER SCOPE e12a90f69e50 bridge bridge local 7514a428f3d0 host host local f1f4981f4fbb none null local [root@pihao ~]#
网络模式
-
bridge 桥接:在docker上搭桥(默认,自己创建也是用bridge模式)
-
none : 不配置网络
-
host : 主机,和宿主机共享网络
-
container : 容器内网络连通(用的少,局限性很大)
测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21# 我们之前直接启动的命令,--net bridge,默认会有这个参数,这个就是我们的docker0 [root@pihao ~]# docker run -d -P --name tomcat01 tomcat [root@pihao ~]# docker run -d -P --name tomcat01 --net bridge tomcat # docker0特点,默认使用的,域名不能访问, --link可以打通连接 # 我们可以自定义一个网络 [root@pihao ~]# docker network create --help Usage: docker network create [OPTIONS] NETWORK Create a network Options: --attachable Enable manual container attachment --aux-address map Auxiliary IPv4 or IPv6 addresses used by Network driver (default map[]) -d, --driver string Driver to manage the Network (default "bridge") # 桥接 --gateway strings IPv4 or IPv6 Gateway for the master subnet # 指定网关 -o, --opt map Set driver specific options (default map[]) --scope string Control the network's scope --subnet strings Subnet in CIDR format that represents a network segment # 设置子网(必须要配置) [root@pihao ~]#
创建一个自己的网络
1
2
3
4
5
6
7
8
9
10
11
12
13# --driver bridge # --subnet 192.168.0.0/16 支持范围: 192.168.0.2~192.168.255.255 # --gateway 192.168.0.1 [root@pihao ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet 8f69e37f277cb7c27c28852076b9d5beafa73c597c2464bbf6d1418710c3e6be [root@pihao ~]# docker network ls NETWORK ID NAME DRIVER SCOPE e12a90f69e50 bridge bridge local 7514a428f3d0 host host local 8f69e37f277c mynet bridge local # 我们自定义的网络 f1f4981f4fbb none null local [root@pihao ~]#
查看自己的网络
再次启动tomcat测试,启动的时候指定我们自己定义的网络 mynet
1
2
3
4
5[root@pihao ~]# docker run -d -P --name tomcat-net-01 --net mynet tomcat b5db4c5c94d049c6caaef2b2ae39c34e9470ac0c4dd44a59bea77b57cce98649 [root@pihao ~]# docker run -d -P --name tomcat-net-02 --net mynet tomcat 28129f9f6304265405274bfbfe3b348a7f70ece8f3772fafed7d955c17ff78ef
启动完毕后再来检查我们的 mynet 网络
最后自定义网络能不能通过容器名来访问,不使用 --link
1
2
3
4
5
6[root@pihao ~]# 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.128 ms 64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.105 ms # 发现可以,没问题
结论:我们自定义网络Docker都已经帮我们维护好了对应的关系,推荐我们平时这样使用网络
好处:保证不同的集群使用不同的网络,保证集群是安全和健康的。因为都在不同的网段!!
网络连通
现有的容器及所在网络:
使用docker0网络下的tomcat01来 Ping 一下mynet 网络下的tomcat-net-01
1
2
3
4
5[root@pihao ~]# docker exec -it tomcat01 ping tomcat-net-01 ping: tomcat-net-01: Name or service not known [root@pihao ~]# 发现不行,肯定不行呀,因为这都属于不同的网段下了 # 思考:那如果我想要他能ping通,该怎么操作呢??
图示:
注意:这里说的 要打通 还不是两个网络直接打通(Docker0打通mynet),而是 容器与网卡打通(tomcat-01 与mynet打通)!!!
如何打通??
1
2
3
4
5
6
7# 测试打通 tomcat01 - mynet [root@pihao ~]# docker network connect mynet tomcat01 # 打通之后查看一下网络 [root@pihao ~]# docker network inspect mynet # 发现连通之后就是将 tomcat01 放到了mynet 网络下 # 这就是所谓的一个容器两个 IP
再来使用 tomcat01 ping 一下 tomcat-net-01
1
2
3
4
5
6
7
8
9
10
11[root@pihao ~]# docker exec -it tomcat01 ping tomcat-net-01 # 发现现在通了(不同的网卡的容器) PING tomcat-net-01 (192.168.0.2) 56(84) bytes of data. 64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.098 ms 64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.100 ms # 而tomcat02是Ping不通的,因为tomcat02没有和 mynet 打通 [root@pihao ~]# docker exec -it tomcat02 ping tomcat-net-01 ping: tomcat-net-01: Name or service not known [root@pihao ~]#
结论:假设要跨网络去操作别人,就需要使用 docker network connect 网络名 容器名 来打通!!!
实战:部署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
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# 创建redis集群的网卡 [root@pihao ~]# docker network create redis --subnet 172.38.0.0/16 # 通过脚本创建六个redis配置 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 # shell配置文件的脚本ok # 启动 第一个 redis docker run -p 6371:6379 -p 16371:16379 --name redis-1 -v /mydata/redis/node-1/data:/data -v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf -d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf # 启动 第二个 redis docker run -p 6372:6379 -p 16372:16379 --name redis-2 -v /mydata/redis/node-2/data:/data -v /mydata/redis/node-2/conf/redis.conf:/etc/redis/redis.conf -d --net redis --ip 172.38.0.12 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf # 启动 第三个 redis docker run -p 6373:6379 -p 16373:16379 --name redis-3 -v /mydata/redis/node-3/data:/data -v /mydata/redis/node-3/conf/redis.conf:/etc/redis/redis.conf -d --net redis --ip 172.38.0.13 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf # 启动 第四个 redis docker run -p 6374:6379 -p 16374:16379 --name redis-4 -v /mydata/redis/node-4/data:/data -v /mydata/redis/node-4/conf/redis.conf:/etc/redis/redis.conf -d --net redis --ip 172.38.0.14 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf # 启动 第五个 redis docker run -p 6375:6379 -p 16375:16379 --name redis-5 -v /mydata/redis/node-5/data:/data -v /mydata/redis/node-5/conf/redis.conf:/etc/redis/redis.conf -d --net redis --ip 172.38.0.15 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf # 启动 第六个 redis 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 # 六个redis启动后: [root@pihao conf]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8be3b0272fa5 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 2 seconds ago Up 1 second 0.0.0.0:6376->6379/tcp, 0.0.0.0:16376->16379/tcp redis-6 7daf1edb4fa3 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 30 seconds ago Up 29 seconds 0.0.0.0:6375->6379/tcp, 0.0.0.0:16375->16379/tcp redis-5 277223569dd6 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" About a minute ago Up About a minute 0.0.0.0:6374->6379/tcp, 0.0.0.0:16374->16379/tcp redis-4 e5455ca3d11b redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 2 minutes ago Up 2 minutes 0.0.0.0:6373->6379/tcp, 0.0.0.0:16373->16379/tcp redis-3 af4a01eb4e49 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 4 minutes ago Up 4 minutes 0.0.0.0:6372->6379/tcp, 0.0.0.0:16372->16379/tcp redis-2 2250d384e975 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 6 minutes ago Up 6 minutes 0.0.0.0:6371->6379/tcp, 0.0.0.0:16371->16379/tcp redis-1 [root@pihao conf]# # 进入启动一个 redis-1的容器 [root@pihao conf]# docker exec -it redis-1 /bin/sh (注意:这里发现redis没有 /bin/bash命令 只有 /bin/sh 命令) # 默认进来的是 /data 目录 /data # ls 查看到有两个文件 appendonly.aof nodes.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 Master[0] -> Slots 0 - 5460 Master[1] -> Slots 5461 - 10922 Master[2] -> Slots 10923 - 16383 # 三台从机slave Adding replica 172.38.0.15:6379 to 172.38.0.11:6379 # 15是11的从机 Adding replica 172.38.0.16:6379 to 172.38.0.12:6379 # 16是12的从机 Adding replica 172.38.0.14:6379 to 172.38.0.13:6379 # 14是13的从机 M: fe1da2ced57ea42176134194c8f919478e938ec7 172.38.0.11:6379 slots:[0-5460] (5461 slots) master M: 2dd905acf6fd1a633c3c2d246fbc78ab166148a8 172.38.0.12:6379 slots:[5461-10922] (5462 slots) master M: 73bc0387c4e7006621cf71201b799a8611c51716 172.38.0.13:6379 slots:[10923-16383] (5461 slots) master S: 35f7de80fc3debca9e8fc6c84c6dfd88291f9695 172.38.0.14:6379 replicates 73bc0387c4e7006621cf71201b799a8611c51716 S: 8a5ef9825fb194d43b02dcc731de3d2a7c28ca79 172.38.0.15:6379 replicates fe1da2ced57ea42176134194c8f919478e938ec7 S: 090fda90e4dcd7ca8466987c7150e3302a9c8662 172.38.0.16:6379 replicates 2dd905acf6fd1a633c3c2d246fbc78ab166148a8 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: fe1da2ced57ea42176134194c8f919478e938ec7 172.38.0.11:6379 slots:[0-5460] (5461 slots) master 1 additional replica(s) S: 8a5ef9825fb194d43b02dcc731de3d2a7c28ca79 172.38.0.15:6379 slots: (0 slots) slave replicates fe1da2ced57ea42176134194c8f919478e938ec7 M: 2dd905acf6fd1a633c3c2d246fbc78ab166148a8 172.38.0.12:6379 slots:[5461-10922] (5462 slots) master 1 additional replica(s) S: 35f7de80fc3debca9e8fc6c84c6dfd88291f9695 172.38.0.14:6379 slots: (0 slots) slave replicates 73bc0387c4e7006621cf71201b799a8611c51716 S: 090fda90e4dcd7ca8466987c7150e3302a9c8662 172.38.0.16:6379 slots: (0 slots) slave replicates 2dd905acf6fd1a633c3c2d246fbc78ab166148a8 M: 73bc0387c4e7006621cf71201b799a8611c51716 172.38.0.13:6379 slots:[10923-16383] (5461 slots) master 1 additional replica(s) [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. # 创建成功啦 # 连接集群 -c 表示的是连接集群 不加的话表示单机 /data # redis-cli -c 127.0.0.1:6379>
查看集群信息
开始测试
1
2# set k1 v1
1
2# docker stop
1
2# get k1 看看能不能拿到值,发现拿到值了,并且发现是通过14这太从机获取到的,说明高可用生效了
docker 搭建redis完成
1
2
3
4
5
6
7
8
9
10
11## 再次查看集群信息,发现172.38.0.13:6379@16379 master,fail,并且172.38.0.14:6379@16379 myself,maste(13挂了,14成了主机) 172.38.0.14:6379> cluster nodes 8a5ef9825fb194d43b02dcc731de3d2a7c28ca79 172.38.0.15:6379@16379 slave fe1da2ced57ea42176134194c8f919478e938ec7 0 1591447999393 5 connected 090fda90e4dcd7ca8466987c7150e3302a9c8662 172.38.0.16:6379@16379 slave 2dd905acf6fd1a633c3c2d246fbc78ab166148a8 0 1591448000397 6 connected 35f7de80fc3debca9e8fc6c84c6dfd88291f9695 172.38.0.14:6379@16379 myself,master - 0 1591448000000 7 connected 10923-16383 fe1da2ced57ea42176134194c8f919478e938ec7 172.38.0.11:6379@16379 master - 0 1591447999000 1 connected 0-5460 73bc0387c4e7006621cf71201b799a8611c51716 172.38.0.13:6379@16379 master,fail - 1591447080985 1591447080000 3 connected 2dd905acf6fd1a633c3c2d246fbc78ab166148a8 172.38.0.12:6379@16379 master - 0 1591447999000 2 connected 5461-10922 172.38.0.14:6379>
我们使用了docker之后,所有的技术都会慢慢变得简单起来!
SpringBoot微服务打包Docker镜像
1、构建SpringBoot项目
2、打包应用
3、编写dockerfile
1
2
3
4
5
6
7
8
9FROM java:8 COPY *.jar /app.jar CMD ["--server.port=8080"] EXPOSE 8080 ENTRYPOINT ["java","-jar","/app.jar"]
4、构建镜像
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
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[root@pihao eclipse]# ls Dockerfile docker-test-0.0.1-SNAPSHOT.jar # 只要这两个文件 [root@pihao eclipse]# docker build -t pihao-docker-test . Sending build context to Docker daemon 16.47MB Step 1/5 : FROM java:8 8: Pulling from library/java 5040bd298390: Pull complete fce5728aad85: Pull complete 76610ec20bf5: Pull complete 60170fec2151: Pull complete e98f73de8f0d: Pull complete 11f7af24ed9c: Pull complete 49e2d6393f32: Pull complete bb9cdec9c7f3: Pull complete Digest: sha256:c1ff613e8ba25833d2e1940da0940c3824f03f802c449f3d1815a66b7f8c0e9d Status: Downloaded newer image for java:8 ---> d23bdf5b1b1b Step 2/5 : COPY *.jar /app.jar ---> cd9911f3fe9c Step 3/5 : CMD ["--server.port=8080"] ---> Running in 5926ef3df86e Removing intermediate container 5926ef3df86e ---> 12bf641f1df0 Step 4/5 : EXPOSE 8080 ---> Running in 1e5a2f7bf6c6 Removing intermediate container 1e5a2f7bf6c6 ---> 658947a6d2b7 Step 5/5 : ENTRYPOINT ["java","-jar","/app.jar"] ---> Running in 4296335cbd4c Removing intermediate container 4296335cbd4c ---> d6df5ff457b9 Successfully built d6df5ff457b9 Successfully tagged pihao-docker-test:latest # 查看构建的镜像 [root@pihao eclipse]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE pihao-docker-test latest d6df5ff457b9 12 seconds ago 660MB tomcat latest 1b6b1fe7261e 3 weeks ago 647MB redis 5.0.9-alpine3.11 3661c84ee9d0 6 weeks ago 29.8MB java 8 d23bdf5b1b1b 3 years ago 643MB # 运行容器 [root@pihao eclipse]# docker run -d -P --name springbootweb-docker pihao-docker-test 39d59e8a9bc26264b418c387f147caac40884eaaf31544c50b29a37dfc8d41 # 查看随机随机生成的端口 [root@pihao eclipse]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 39d59e8a9bc2 pihao-docker-test "java -jar /app.jar …" 41 seconds ago Up 40 seconds 0.0.0.0:32777->8080/tcp springbootweb-docker # 访问测试 [root@pihao eclipse]# curl localhost:32777/hello hello [root@pihao eclipse]# # 完美运行
思考:如果有很多镜像呢??100个镜像,要怎么管理??
Docker Compose
Docker Swarm
CI/CD之Jenkins
只要学不死,就往死里学!!!
最后
以上就是自信白昼最近收集整理的关于Docker入门详细教程,全网最全!Docker的全部内容,更多相关Docker入门详细教程内容请搜索靠谱客的其他文章。
发表评论 取消回复