一、Docker安装
1、获取官方帮助文档
1.从官网最下方Docs选项中打开帮助文档。
2.选择下载并安装
3.选择linux
4.左侧选择在centos中安装
可以看到此页为centos7中安装docker的官方教程
2、安装Docker
#卸载命令
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
#需要的安装包
yum install -y yum-utils
#设置镜像仓库
yum-config-manager \
--add-repo \
https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo#默认为国外镜像仓库,此处替换为阿里云
#更新软件包索引
yum makecache fast
#安装docker相关内容,docker-ce为社区版,docker-ee为企业版
yum install docker-ce docker-ce-cli containerd.io
#启动docker
systemctl start docker
#验证是否启动成功
docker version
#有以上信息说明安装成功
#hello world(此步之前可能需要提前配置镜像加速)
docker run hello-world
#输出以下结果
#查看镜像信息
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest d1165f221234 5 months ago 13.3kB
#配置镜像加速
#登录阿里云,找到右上角控制台面板,打开后搜索容器镜像服务
#打开最下方镜像加速器
#输入右方给出的所有命令
mkdir -p /etc/docker#创建加速文件目录
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["阿里云给出的加速网址"]
}
EOF
systemctl daemon-reload
systemctl restart docker
二、Run的流程和Docker原理
1、回顾hello-world流程
hello-world是如何启动的
通过上图可以得出以下工作流程图
2、底层原理
Docker是怎么工作的?
Docker是一个client-server结构的系统,Docker的守护进程运行在主机上。客户端通过socket来访问。
Docker-server接收到Docker-client的指令后执行指令。
Docker为什么比虚拟机快?
1.Docker有着比虚拟机更少的抽象层。
2.Docker利用的是宿主机的内核,虚拟机需要Guest OS。Docker是在主机上直接安装Docker服务,所有的东西都运行在Docker服务上。
如图
所以,新建一个容器时,Docker不需要和虚拟机一样加载一个完整的操作系统,自然比虚拟机更快。
三、Docker的常用命令
1、帮助命令
docker version #显示版本信息
docker info #显示详细信息
docker '命令' --help #显示命令信息
2、帮助文档
帮助文档的地址:https//docs.docker.com/engine/reference/commandline/
在官方帮助文档中能查看所有命令信息
3、镜像命令
docker images
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest d1165f221234 5 months ago 13.3kB
REPOSITORY #镜像仓库源(镜像名)
TAG #镜像标签(版本标签)
IMAGE ID #镜像id
CREATED #镜像创建时间
SIZE #镜像大小
#可选项
-a, --all #显示所有信息(列出所有镜像)
-q, --quiet #只显示id
docker search
[root@localhost ~]# docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 11308 [OK]
mariadb MariaDB Server is a high performing open sou… 4297 [OK]
mysql/mysql-server Optimized MySQL Server Docker images. Create… 838 [OK]
percona Percona Server is a fork of the MySQL relati… 550 [OK]
phpmyadmin phpMyAdmin - A web interface for MySQL and M… 300 [OK]
#可选项
-f, --filter='条件' #通过条件过滤
docker pull
[root@localhost ~]# docker pull mysql
Using default tag: latest
latest: Pulling from library/mysql
e1acddbe380c: Pull complete #分层下载,联合文件系统,docker的灵魂。
bed879327370: Pull complete
03285f80bafd: Pull complete
ccc17412a00a: Pull complete
1f556ecc09d1: Pull complete
adc5528e468d: Pull complete
1afc286d5d53: Pull complete
6c724a59adff: Pull complete
0f2345f8b0a3: Pull complete
c8461a25b23b: Pull complete
3adb49279bed: Pull complete
77f22cd6c363: Pull complete
Digest: sha256:d45561a65aba6edac77be36e0a53f0c1fba67b951cb728348522b671ad63f926
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest
docker rmi
[root@localhost ~]# docker rmi -f 镜像id #删除指定镜像
[root@localhost ~]# docker rmi -f 镜像id 镜像id 镜像id #删除多个镜像
[root@localhost ~]# docker rmi -f $(docker images -aq) #按id删除所有镜像
Untagged: mysql:latest
Untagged: mysql@sha256:d45561a65aba6edac77be36e0a53f0c1fba67b951cb728348522b671ad63f926
Deleted: sha256:5a4e492065c722ec8cc7413552bafc6fd5434c5ad90797e898ccc4e347e21aa5
Deleted: sha256:816bf92c28337cd97393cb1fab7697398c9b657baa8e80ad394e1193bdd7c323
Deleted: sha256:4d9cad11f64589b397b1033d6f14cea1794efbee0a9923932fb3394a67cb9812
Deleted: sha256:d8cc28a31b469770ffe2239a29aaef8745fedc4df3c545b1615ba864796709a3
Deleted: sha256:c65a377e07f1205f3c28f7067d2ac4da3a65fbe7c1b4606b48028db3818d2f4c
Deleted: sha256:7dcd840f1d4be1a565f470453489932a17c62ed36b959d7839f004606ba22f0b
Deleted: sha256:1438a7497295aed687ea1875073a1f9faa6a308f787767b952da4a1a21e2c2c6
Deleted: sha256:c728863b4742db55b9630b0129abac718c8c9704e5ed86e8af93dfb47a0f6214
Deleted: sha256:0f12df3ff796b6fb619c63bf2f78f16d1033746e19f75ffc2d8d72ea69242ad4
Deleted: sha256:3072318e40ebff019298a59290e615ad6170a651f3121c0e356dcf3dd7426136
Deleted: sha256:a69e3133dd3c0a81bd439120abb8f98e43c1581629896725b968db906c8fdfac
Deleted: sha256:6d9498fd63c38c4b0b9bbc563087b4bc164b2fb5211832a8d43c60a9692a7f84
Deleted: sha256:f68ef921efae588b3dd5cc466a1ca9c94c24785f1fa9420bea15ecc2dedbe781
Untagged: hello-world:latest
Untagged: hello-world@sha256:0fe98d7debd9049c50b597ef1f85b7c1e8cc81f59c8d623fcb2250e8bec85b38
Deleted: sha256:d1165f2212346b2bab48cb01c1e39ee8ad1be46b87873d9ca7a4e434980a7726
#可选项
-f #按id删除镜像
#在docker rmi -f $(docker images -aq)报错的情况下
1)批量停止container:
sudo docker ps -a | awk '{print $1}'| grep -v CONTAINER | xargs sudo docker stop
2)批量删除container:
sudo docker images | awk '{print $3}' | grep -v IMAGE | xargs sudo docker rmi
3)批量删除image:
sudo docker images | awk '{print $1}' | grep -v REPOSITORY | xargs sudo docker rmi
4、容器命令
要先下载镜像才能创建容器
新建容器并启动
[root@localhost ~]# docker pull centos
Using default tag: latest
latest: Pulling from library/centos
7a0437f04f83: Pull complete
Digest: sha256:5528e8b1b1719d34604c87e11dcd1c0a20bedf46e83b5632cdeac91b8c04efc1
Status: Downloaded newer image for centos:latest
docker.io/library/centos:latest
在centos中再下载一个centos镜像,之后操作都在该镜像中
run
docker run [可选参数] image
#参数说明
--name='name' #容器命名
-d #以后台方式运行
-it #使用交互方式运行(进入容器查看内容)
-p(小写) #指定容器端口
-p 'port':'port' #端口映射,前者为主机端口,后者为容器端口
-p ip:'port':'port'
-p 'port' #容器端口
-P(大写) #使用随机端口
可以看出,用户名已经变为该镜像的id,在xshell中显示的文件夹颜色也与主机不同。
镜像中的系统很多都是不完善的,甚至很多基础命令都用不了。
ps
[root@localhost /]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e25018a0b96d centos "/bin/bash" About a minute ago Exited (0) About a minute ago pedantic_knuth
98d1443a7c2d centos "/bin/bash" 9 minutes ago Exited (0) 2 minutes ago infallible_raman
bc63240bf7da d1165f221234 "/hello" 5 hours ago Exited (0) 5 hours ago happy_archimedes
#可选项
-a #列出所有运行过的容器
-n='num' #显示最近创建过的几个容器
-q #只显示编号
退出容器
exit #停止容器并退出
ctrl+p+q #退出容器不停止
删除容器
rm '容器id' #删除指定id的容器,不能删除运行中的容器
rm -f #强制删除
rm -f $(docker ps -aq) #强制删除所有容器(按id)
开启和停止容器
docker start '容器id'
docker restart '容器id'
docker stop '容器id'
docker kill '容器id'
#含义与Linux基础操作相同
四、常用其他命令
1、后台启动
#命令docker run -d '镜像名'
[root@localhost /]# docker run -d centos
3aac07f49b2922859b6cb4aa3f5adf21b5278170a599380dae01bbbc90a2538d
[root@localhost /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
#问题:后台启动后进程自动停止
#docker容器使用后台启动时,必须要有一个前台进程,否则会自动停止。
#比如nginx容器启动后,发现自己没有提供服务就立刻停止(自杀),他认为自己没有程序了。
2、查看日志
docker logs -f -t --tail #发现容器没有日志
#自己写一段shell脚本
"while true;do echo 123456;sleep 1;done"
[root@localhost /]# docker run -d centos /bin/sh -c "while true;do echo 123456;sleep 1;done"
372dd788f6ee829092a28d94dc40536725767d8acce4907f4c99ebbf0658821a
[root@localhost /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
372dd788f6ee centos "/bin/sh -c 'while t…" 6 seconds ago Up 6 seconds festive_banach
[root@localhost /]# docker logs -f -t --tail 10 372dd788f6ee
2021-08-23T07:43:30.674632053Z 123456
2021-08-23T07:43:31.680282821Z 123456
2021-08-23T07:43:32.685241177Z 123456
2021-08-23T07:43:33.689979428Z 123456
2021-08-23T07:43:34.694671996Z 123456
2021-08-23T07:43:35.699345232Z 123456
2021-08-23T07:43:36.701925301Z 123456
2021-08-23T07:43:37.707651945Z 123456
2021-08-23T07:43:38.712024853Z 123456
2021-08-23T07:43:39.717165858Z 123456
3、查看容器中进程信息
#docker top 容器id
[root@localhost /]# docker top 372dd788f6ee
UID PID PPID C STIME TTY TIME CMD
root 3784 3766 0 15:43 ? 00:00:00 /bin/sh -c while true;do echo 123456;sleep 1;done
4、查看元数据
#docker inspect 容器id
[root@localhost /]# docker inspect [root@localhost /]# docker top 372dd788f6ee
15:43 ? 00:00:00 /bin/sh -c while true;do echo 123456;sleep 1;done[
{
"Id": "372dd788f6ee829092a28d94dc40536725767d8acce4907f4c99ebbf0658821a",
"Created": "2021-08-23T07:43:05.344582092Z",
"Path": "/bin/sh",
"Args": [
"-c",
"while true;do echo 123456;sleep 1;done"
],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 3784,
"ExitCode": 0,
"Error": "",
"StartedAt": "2021-08-23T07:43:05.574506929Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:300e315adb2f96afe5f0b2780b87f28ae95231fe3bdd1e16b9ba606307728f55",
"ResolvConfPath": "/var/lib/docker/containers/372dd788f6ee829092a28d94dc40536725767d8acce4907f4c99ebbf0658821a/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/372dd788f6ee829092a28d94dc40536725767d8acce4907f4c99ebbf0658821a/hostname",
"HostsPath": "/var/lib/docker/containers/372dd788f6ee829092a28d94dc40536725767d8acce4907f4c99ebbf0658821a/hosts",
"LogPath": "/var/lib/docker/containers/372dd788f6ee829092a28d94dc40536725767d8acce4907f4c99ebbf0658821a/372dd788f6ee829092a28d94dc40536725767d8acce4907f4c99ebbf0658821a-json.log",
"Name": "/festive_banach",
"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/95a49af620be163b33fe6f0a9681d37b4cc6fb75afb3ae8a224398e569ae6c00-init/diff:/var/lib/docker/overlay2/ab93883db72a081f0d5eecb5fcaff382dffa1f2f2c915d22f3a3e1428d896eac/diff",
"MergedDir": "/var/lib/docker/overlay2/95a49af620be163b33fe6f0a9681d37b4cc6fb75afb3ae8a224398e569ae6c00/merged",
"UpperDir": "/var/lib/docker/overlay2/95a49af620be163b33fe6f0a9681d37b4cc6fb75afb3ae8a224398e569ae6c00/diff",
"WorkDir": "/var/lib/docker/overlay2/95a49af620be163b33fe6f0a9681d37b4cc6fb75afb3ae8a224398e569ae6c00/work"
},
"Name": "overlay2"
},
"Mounts": [],
"Config": {
"Hostname": "372dd788f6ee",
"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 123456;sleep 1;done"
],
"Image": "centos",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {
"org.label-schema.build-date": "20201204",
"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": "13e2242df7972d99ec7156e47b8bf361da503ac6cc58030b5f91a9ecda3e5b60",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {},
"SandboxKey": "/var/run/docker/netns/13e2242df797",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "486e5fb90796a110e6e3ca6ca6bbbc4da7a20e5e2dccbeaf86651f4a39598c8a",
"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": "48ae67fce883d011a5fe013dd66c34da546011767dbaabda4b4e83cf54c9850f",
"EndpointID": "486e5fb90796a110e6e3ca6ca6bbbc4da7a20e5e2dccbeaf86651f4a39598c8a",
"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
}
}
}
}
]
Error: No such object: [root@localhost
Error: No such object: /]#
Error: No such object: docker
Error: No such object: top
[root@localhost /]# UID PID PPID C STIME TTY TIME CMD
-bash: UID: command not found
[root@localhost /]# root 3784 3766 0 15:43 ? 00:00:00 /bin/sh -c while true;do echo 123456;sleep 1;done
-bash: syntax error near unexpected token `do'
5、进入当前正在运行的容器
#容器通常是使用后台运行的
#需要进入容器修改配置
docker exec -it 容器id /bin/bash #在容器中打开新终端进入
[root@localhost /]# docker exec -it 372dd788f6ee /bin/bash
[root@372dd788f6ee /]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 07:43 ? 00:00:00 /bin/sh -c while true;do echo 123456;sleep 1;done
root 973 0 0 07:59 pts/0 00:00:00 /bin/bash
root 1025 1 0 07:59 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1
root 1026 973 0 07:59 pts/0 00:00:00 ps -ef
[root@372dd788f6ee /]# top
top - 08:00:16 up 7:21, 0 users, load average: 0.03, 0.02, 0.05
Tasks: 4 total, 1 running, 3 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni, 97.4 id, 0.0 wa, 0.0 hi, 2.6 si, 0.0 st
MiB Mem : 972.3 total, 112.2 free, 347.8 used, 512.4 buff/cache
MiB Swap: 512.0 total, 510.7 free, 1.3 used. 467.9 avail Mem
docker attach 容器id #进入容器正在运行的终端
[root@localhost /]# docker attach 372dd788f6ee
6、容器与主机间拷贝
#只要容器在,容器数据就在,与容器在不在运行没有关系。
[root@localhost ~]# docker run -it centos /bin/bash
[root@90a0ef45de5d /]#
[root@localhost ~]# cd /home
[root@localhost home]# docker ps #查看容器id,方便下一步操作
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
90a0ef45de5d centos "/bin/bash" About a minute ago Up About a minute festive_hofstadter
[root@localhost home]# docker attach 90a0ef45de5d #进入容器
[root@90a0ef45de5d /]# cd home
[root@90a0ef45de5d home]# ls
[root@90a0ef45de5d home]# touch 123.321 #新建文件夹123.321
[root@90a0ef45de5d home]# exit #直接退出
exit
[root@localhost home]# docker cp 90a0ef45de5d:/home/123.321 /home #拷贝容器中123.321到主机/home目录
[root@localhost home]# ls
123.321 dockerstudy
7、命令小结
#删除所有已停止的容器
docker rm -v $(docker ps -aq -f status=exited)
五、部署操作
1、nginx部署
问题:linux端口未开启
#从镜像仓库中拉取nginx,在拉取前建议先去docker官网查看nginx的相关信息
[root@localhost home]# docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
e1acddbe380c: Pull complete
e21006f71c6f: Pull complete
f3341cc17e58: Pull complete
2a53fa598ee2: Pull complete
12455f71a9b5: Pull complete
b86f2ba62d17: Pull complete
Digest: sha256:4d4d96ac750af48c6a551d757c1cbfc071692309b491b70b2b8976e102dd3fef
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest
#查看有没有安装成功
[root@localhost home]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest dd34e67e3371 5 days ago 133MB #有则说明安装成功
centos latest 300e315adb2f 8 months ago 209MB
[root@localhost ~]# docker run -d --name=nginx01 -p 3344:80 nginx #后台运行(-d)nginx,将其命名为nginx01(--name)并将3344端口与80端口进行映射(-p 3344:80)
e6fd7157617fecfffac1cce70d03a34c5f2f3f9909c3ec354452af791289a3de #运行成功
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e6fd7157617f nginx "/docker-entrypoint.…" 8 seconds ago Up 3 seconds 0.0.0.0:3344->80/tcp, :::3344->80/tcp nginx01
[root@localhost ~]# curl localhost:3344 #连接本地3344端口查看nginx运行情况
<!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>
#具体映射原理如图
2、tomcat部署
[root@localhost ~]# docker pull tomcat:9.0 #下载指定版本tomcat
9.0: Pulling from library/tomcat
1cfaf5c6f756: Pull complete
c4099a935a96: Pull complete
f6e2960d8365: Pull complete
dffd4e638592: Pull complete
a60431b16af7: Pull complete
4869c4e8de8d: Pull complete
9815a275e5d0: Pull complete
c36aa3d16702: Pull complete
cc2e74b6c3db: Pull complete
1827dd5c8bb0: Pull complete
Digest: sha256:1af502b6fd35c1d4ab6f24dc9bd36b58678a068ff1206c25acc129fb90b2a76a
Status: Downloaded newer image for tomcat:9.0
docker.io/library/tomcat:9.0
[root@localhost ~]# docker run -d -p 3333:8080 --name tomcat01 tomcat
9f57e8f090adcc14d9cae93ea2adc50786aa99dd73a4b40ca73ebdb3a09c293b
[root@localhost ~]#
#发现可以访问,但是连不上。
#原因为阿里云镜像为了追求性能不是完整版,剔除所有不必要功能
[root@localhost ~]# docker exec -it tomcat01 /bin/bash
root@9f57e8f090ad:/usr/local/tomcat# ls
BUILDING.txt LICENSE README.md RUNNING.txt conf logs temp webapps.dist
CONTRIBUTING.md NOTICE RELEASE-NOTES bin lib native-jni-lib webapps work
root@9f57e8f090ad:/usr/local/tomcat# cd webapps
root@9f57e8f090ad:/usr/local/tomcat/webapps# ls
root@9f57e8f090ad:/usr/local/tomcat/webapps#
#可见webapps目录下内容为空
[root@localhost ~]# docker exec -it tomcat01 /bin/bash
root@9f57e8f090ad:/usr/local/tomcat# ls
BUILDING.txt LICENSE README.md RUNNING.txt conf logs temp webapps.dist
CONTRIBUTING.md NOTICE RELEASE-NOTES bin lib native-jni-lib webapps work
root@9f57e8f090ad:/usr/local/tomcat# cd webapps
root@9f57e8f090ad:/usr/local/tomcat/webapps# ls
root@9f57e8f090ad:/usr/local/tomcat/webapps# cd ../webapps.dist/
root@9f57e8f090ad:/usr/local/tomcat/webapps.dist# ls
ROOT docs examples host-manager manager
root@9f57e8f090ad:/usr/local/tomcat/webapps.dist# cd ..
root@9f57e8f090ad:/usr/local/tomcat# cp -r webapps.dist/* webapps
#浏览发现项目文件在webapp.dist中
#复制webapp.dist中所有内容进入webapp中
#刷新网页,连接成功
3、elasticsearch+kibana部署
[root@localhost ~]# docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2 #一键下载并运行
Unable to find image 'elasticsearch:7.6.2' locally
7.6.2: Pulling from library/elasticsearch
ab5ef0e58194: Pull complete
c4d1ca5c8a25: Pull complete
941a3cc8e7b8: Pull complete
43ec483d9618: Pull complete
c486fd200684: Pull complete
1b960df074b2: Pull complete
1719d48d6823: Pull complete
Digest: sha256:1b09dbd93085a1e7bca34830e77d2981521a7210e11f11eda997add1c12711fa
Status: Downloaded newer image for elasticsearch:7.6.2
e89c068274204f9b9f0a2f7b7b61c9a48aaca4fca2ed5447723f9f7cd971ae56
#开启后发现并没有发现该容器
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
#经过检查发现内存不足
[root@localhost ~]# docker run -it --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch
OpenJDK 64-Bit Server VM warning: INFO: os::commit_memory(0x0000000085330000, 2060255232, 0) failed; error='Cannot allocate memory' (errno=12)
#
# There is insufficient memory for the Java Runtime Environment to continue.
# Native memory allocation (mmap) failed to map 2060255232 bytes for committing reserved memory.
# An error report file with more information is saved as:
# /tmp/hs_err_pid1.log
#通过-e添加配置后限制使用内存
[root@localhost ~]# docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch
f064a6c4e4c347b7c051c4fa05d49478a653971bf7f7534f769c968f5b62c5aa
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f064a6c4e4c3 elasticsearch "/docker-entrypoint.…" 7 seconds ago Up 6 seconds 0.0.0.0:9200->9200/tcp, :::9200->9200/tcp, 0.0.0.0:9300->9300/tcp, :::9300->9300/tcp elasticsearch
[root@localhost ~]#
#成功启动
[root@localhost ~]# curl localhost:9200
{
"name" : "gURmP-k",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "MVh7cQmMTOqnyU53Pr-cwQ",
"version" : {
"number" : "5.6.12",
"build_hash" : "cfe3d9f",
"build_date" : "2018-09-10T20:12:43.732Z",
"build_snapshot" : false,
"lucene_version" : "6.6.1"
},
"tagline" : "You Know, for Search"
}
[root@localhost ~]#
#通过docker state查看内存使用
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
f064a6c4e4c3 elasticsearch 0.27% 275.4MiB / 972.3MiB 28.32% 3.27kB / 3.82kB 51.9MB / 41kB 30
4、portainer可视化面板安装
portainer是dockers的可视化图形管理界面,方便管理。
[root@localhost ~]# docker run -d -p 8088:9000\ #安装并进行8088端口映射
> --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer #挂载
访问测试:
注册以后选择local,打开以后可以进行管理
六、镜像
1、什么是镜像
镜像是一种轻量级的独立软件包,包含软件运行所需的所有内容,如代码、库、环境变量和配置文件。
所有的应用,直接打包docker镜像就能运行。
如何得到镜像?
· 官网安装
· 找人拷贝
· 自己制作
2、联合文件系统
联合文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。
联合文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特性:一次加载多个文件系统,但是从外面看来只能看见一个。联合加载会把各层叠加起来,这样最终文件系统就会包含所有底层文件和目录。
docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。
镜像加载原理
**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等等。
所以一个完整的centos镜像有一两G而docker中的centos镜像只有200M
3、分层理解
回顾之前下载时的信息
[root@localhost home]# docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
e1acddbe380c: Pull complete
e21006f71c6f: Pull complete
f3341cc17e58: Pull complete
2a53fa598ee2: Pull complete
12455f71a9b5: Pull complete
b86f2ba62d17: Pull complete
Digest: sha256:4d4d96ac750af48c6a551d757c1cbfc071692309b491b70b2b8976e102dd3fef
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest
可以看到它是一层一层在下载
为什么采用分层结构
最大的好处,是资源共享,比如有多个镜像都是由相同的Base镜像构建来的,宿主机只需要在磁盘中保留一份base镜像,内存中也只需加载一份base镜像,就可以为所有的容器服务。
镜像的每一层都能被共享。
[root@localhost ~]# docker image pull redis
Using default tag: latest
latest: Pulling from library/redis
e1acddbe380c: Already exists
a31098369fcc: Pull complete
4a49b0eba86d: Pull complete
fddf1399efac: Pull complete
5c6658b59b72: Pull complete
0b88638a5b77: Pull complete
Digest: sha256:66ce9bc742609650afc3de7009658473ed601db4e926a5b16d239303383bacad
Status: Downloaded newer image for redis:latest
docker.io/library/redis:latest`
#安装redis
# docker image inspect redis:latest 使用该命令查看分层信息
"Layers": [
"sha256:f68ef921efae588b3dd5cc466a1ca9c94c24785f1fa9420bea15ecc2dedbe781",
"sha256:b6fc243eaea74d1a41b242da4c3ec5166db80f38c4d57a10ce8860c00d902ace",
"sha256:ec92e47b7c52dacc26df07ee13e8e81c099b5a5661ccc97b06692a9c9d01e772",
"sha256:4be6d4460d3615186717f21ffc0023b168dce48967d01934bbe31127901d3d5c",
"sha256:992463b683270e164936e9c48fa395d05a7b8b5cc0aa208e4fa81aa9158fcae1",
"sha256:0083597d42d190ddb86c35587a7b196fe18d79382520544b5f715c1e4792b19a"
]
理解:
特点
Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部,这一层就叫容器层,下面的都是镜像层。
所有操作都基于容器层。
4、commit镜像
如何创建一个自己的镜像
docker commit 提交容器成为一个新的副本
docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[版本标签]
实战测试:
[root@localhost ~]# docker run -it tomcat
#启动一个默认的tomcat
[root@localhost ~]# docker exec -it 6b462dea96a9 /bin/bash
root@6b462dea96a9:/usr/local/tomcat# ls
BUILDING.txt LICENSE README.md RUNNING.txt conf logs temp webapps.dist
CONTRIBUTING.md NOTICE RELEASE-NOTES bin lib native-jni-lib webapps work
root@6b462dea96a9:/usr/local/tomcat# cd webapps
root@6b462dea96a9:/usr/local/tomcat/webapps# ls
root@6b462dea96a9:/usr/local/tomcat/webapps# cd ..
root@6b462dea96a9:/usr/local/tomcat# cp -r webapps.dist/* webapps
root@6b462dea96a9:/usr/local/tomcat#
#打开一个新窗口并将webapps.dist下所有内容拷贝到webapp下
官方默认版本的tomcat是没有工程文件的,我们经过拷贝后将文件复制到了目录中
每次重新启动后都要复制一遍,很麻烦
[root@localhost ~]# docker commit -a="tang" -m="add webapps" 6b462dea96a9 tomcat1:1.0
sha256:f470dbccd61815da8a1ab973b155b1a4a49e9231aef406f3213525a15965d988
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat1 1.0 f470dbccd618 4 seconds ago 673MB`
#可以看到修改后的镜像已经出现在自己的本地镜像中
#与原版比较
这样一来以后就能使用自己修改过的镜像q(≧▽≦q)
七、容器数据卷
1、什么是数据卷
如果数据存储在一个容器中,那么容器删除,数据就会丢失,所以数据需要持久化。
比如:安装MySQL,容器删了就相当于删库跑路(o゜▽゜)o
需求:数据同时存储在本地
容器之间数据共享,docker产出数据同步到本地,这就是卷技术
2、使用数据卷
直接使用命令挂载
docker run -it -v 主机目录:容器目录
#测试
[root@localhost ~]# cd /home
[root@localhost home]# ls
123.321 dockerstudy
[root@localhost home]# docker run -it -v /home/thw:/home centos /bin/bash
[root@0bd59c4d870b /]# cd home
[root@0bd59c4d870b home]# ls
[root@0bd59c4d870b home]#
[root@localhost home]# docker inspect 0bd59c4d870b
#查看详细信息
可以看到挂载信息。
两边对照
此挂载为双向挂载。
3、实战,安装mysql
[root@localhost thw]# docker run -d -p 5555:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=thw2018405A339 --name mysql01 mysql #端口映射,多重挂载,设置密码
cd23bbae411b165ea1727a594c889ebdca2f1f786594b072d48fed61ec7e237b
[root@localhost thw]#
因为不是服务器也没有下载sqlyog所以不再进行测试,但是理论来说可以连接
4、具名和匿名挂载
以上所有挂载都是匿名挂载,具名挂载就是在绝对路径前加上自定义名称,可以通过docker volume ls查找到
-v 卷名:主机路径:容器路径
八、Dockerfile
1、初识dockerfile
创建镜像方式二:Dockerfile
Dockerfile就是用来构建镜像的构建文件,本质上是一段命令脚本。
#现在已知镜像是分层的,每个脚本命令就对应镜像里的一层。
#新建dockerfile文件并在其中写入脚本。
FROME centos #内容
VOLUME ["volume01","volume02"] #挂载
CMD echo "------end------" #运行结束后的输出
CMD /bin/bash
#运行脚本生成镜像
[root@localhost DOCKER-THW]# docker build -f /home/DOCKER-THW/dockerfile1 -t thw/centos:0.1 . #一定记住最后有个"."
Sending build context to Docker daemon 2.048kB
Step 1/4 : FROM centos
---> 300e315adb2f
Step 2/4 : VOLUME ["volume01","volume02"]
---> Running in 4309a3239c8a
Removing intermediate container 4309a3239c8a
---> 90eaa716461b
Step 3/4 : CMD echo "------end------"
---> Running in 8eddba8768d7
Removing intermediate container 8eddba8768d7
---> 72a4797101fa
Step 4/4 : CMD /bin/bash
---> Running in cdd3956d65fe
Removing intermediate container cdd3956d65fe
---> 4cda57e04ee8
Successfully built 4cda57e04ee8
Successfully tagged thw/centos:0.1
#查看生成的镜像
[root@localhost DOCKER-THW]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
thw/centos 0.1 4cda57e04ee8 About a minute ago 209MB
#运行镜像
#可以看到生成时自动挂载的数据卷目录
这两个目录一定有对应的外部目录
经过docker inspect查看结果如下
在volume目录下创建文件
查看挂载的文件
2、数据卷容器
多个容器间互相挂载
首先启动容器
挂载
创建文件查看挂载情况
多个容器同时挂载同样适用
总结:数据卷容器的生命周期一直持续到没有容器使用为止。
但是一旦持久化到了本地,容器内数据会丢失,本地的数据能保留下来。
3、Dockerfile介绍
构建步骤:
- 编写一个dockerfile文件
- 使用docker build 将dockerfile构建成为镜像
- docker run运行镜像
- docker push发布镜像
查看官方操作
点击下方任意标签后发现打开的页面为上传dockerfile的地址,也就是说官方也是通过dockerfile来创建并上传镜像的
4、Dockerfile构建过程
基础知识
- 每个保留关键字(指令)必须是大写字母
- 执行时从上到下顺序执行
- #表示注释
- 每一行指令都会创建并提交一个新的镜像层
5、Dockerfile指令
FROM #基础镜像
LABEL #作者信息(姓名+邮箱)
RUN #镜像构建时需要运行的命令
ADD #添加内容(镜像中需要加入的东西)
WORKDIR #镜像的工作目录
VOLUME #挂载位置
EXPOSE #暴露端口
CMD #指定容器启动时需要运行的命令,只有最后一个会生效(替换之前的命令)
ENTRYPOINT #指定容器启动时需要运行的命令,追加在前面的命令之后
ONBUILD #指令触发器,构建被继承的Dockerfile时使用
COPY #将文件拷贝到镜像中
ENV #设置环境变量
6、实战,构建自己的CentOS
绝大多数的官方镜像都是从stratch开始,然后配置自己需要的软件和配置
#编写配置文件
[root@localhost dockerfile]# cat mycentos
FROM centos
LABEL author=thw mail=897588108@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
#通过文件构建镜像
[root@localhost dockerfile]# docker build -f mycentos -t mycentos:1.0 .
Sending build context to Docker daemon 2.048kB
Step 1/10 : FROM centos
---> 300e315adb2f
Step 2/10 : LABEL author=thw mail=897588108@qq.com
---> Running in d87ee8a8e22b
Removing intermediate container d87ee8a8e22b
---> 32b7f0e99e2e
Step 3/10 : ENV MYPATH /usr/local
---> Running in 83eaba056a27
Removing intermediate container 83eaba056a27
---> dbff07dc48b6
Step 4/10 : WORKDIR $MYPATH
---> Running in 8e76683af0c9
Removing intermediate container 8e76683af0c9
---> aceb74ed9520
Step 5/10 : RUN yum -y install vim
---> Running in 0b0d135e4aea
CentOS Linux 8 - AppStream 2.0 MB/s | 8.8 MB 00:04
.
.
.
Complete!
Removing intermediate container 0b0d135e4aea
---> ae628d1f88e9
Step 6/10 : RUN yum -y install net-tools
---> Running in 61ede7ec5e6f
Removing intermediate container 61ede7ec5e6f
---> ef3391e56e9a
Step 7/10 : EXPOSE 80
---> Running in a2f104fd414c
.
.
.
Removing intermediate container a2f104fd414c
---> d712a91d7714
Step 8/10 : CMD echo $MYPATH
---> Running in 1502a16408ba
Removing intermediate container 1502a16408ba
---> 97a32fe4eb17
Step 9/10 : CMD echo "------end------"
---> Running in 192c1380af93
Removing intermediate container 192c1380af93
---> 62346a236b25
Step 10/10 : CMD /bin/bash
---> Running in ae1808979e8e
Removing intermediate container ae1808979e8e
---> ba1b9211f537
Successfully built ba1b9211f537
Successfully tagged mycentos:1.0
#运行生成的镜像
[root@localhost dockerfile]# docker run -it mycentos:1.0
[root@0baa928f04d5 local]# pwd
/usr/local #直接进入工作目录(MYPATH)
[root@0baa928f04d5 local]#
增加之后的镜像:
利用history命令列出镜像本地变更历史
7、实战,制作tomcat镜像
1.准备tomcat的jdk压缩包
2.编写dockerfile文件
3.构建镜像
4.运行测试
5.访问测试
6.发布项目(因为做了卷挂载,直接在本地编写项目就能发布)
九、上传镜像
发布到DockerHub
1.进入DockerHub,注册账号
2.确定账号可以登录
3.在服务器上提交自己的镜像
[root@localhost ~]# 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
4.用push命令提交镜像
[root@localhost ~]# docker push --help
Usage: docker push [OPTIONS] NAME[:TAG]
Push an image or a repository to a registry
Options:
-a, --all-tags Push all tagged images in the repository
--disable-content-trust Skip image signing (default true)
-q, --quiet Suppress verbose output
发布到阿里云
1.登录阿里云
2.找到容器镜像服务
3.创建个人实例
4.创建并打开命名空间
5.创建容器镜像
6.上传镜像
十、小结
十一、Docker网络
1、网卡
使用ip addr命令查看网卡信息会发现有三个网卡
其中,lo为本机回环地址,ens33为主机ip地址,docker0为docker安装时生成的地址。
docker 是如何处理容器网络访问的?
测试
[root@localhost ~]# docker run -d -P --name tomcat01 tomcat
#查看容器内部网络地址
[root@localhost ~]# docker exec -it tomcat01 ip addr
发现容器启动时会获得一个docker分配的ip地址,通inet信息可推测,最多可生成65535个ip
测试Linux能不能ping通容器内部
发现可以ping通
原理
- 只要安装了docker,就会多出一块网卡。网卡通过桥接模式连接,使用了evth-pair技术。
- 我们每启动一个docker容器,docker就会给它分配一个ip。
- 再次测试ip addr 发现
- evth-pair是一对虚拟设备接口,一端连接协议,一端彼此相连。通常充当桥梁来连接各种虚拟网络设备。open stack、docker容器、ovs的连接都是通过evth-pair来进行的。
测试容器间连通性
原理
Docker使用了Linux的桥接,宿主机充当容器之间的网桥:docker0
Docker中所有的接口都是虚拟的,转发效率高
只要容器删除,对应的网桥也随之删除
2、–link
通过服务名ping,在启动命令中添加–link命令
但是反向是ping不通的。
通过docker network inspect 查看相关信息
进入容器3查看hosts信息
可以看到其中配置了tomcat02的地址信息
但tomcat02中没有tomcat03的信息,所以无法反向ping通
总之,因为种种弊端,–link不建议使用。
3、自定义网络
网络模式
bridge:桥接模式(默认)
none:不配置
host:和宿主机共享网络
container:容器间联通(用的少)
自己创建网络
--driver bridge #模式
--subnet 192.168.0.0/16 #子网地址
--gateway 192.168.0.1 #网关
mynet #网络名称
到此为止,自己的网络就创建好了
此时如果在打开容器时设置使用自定义网络,在此配置文件下“network”下方就会多出对应容器的网络配置。
使用参数:--net
此时,是可以通过容器名双向ping通的
4、网络联通
如图,有没有办法能让不同网络之间联通?
配置如下的tomcat容器
#尝试联通tomcat01与mynet
docker network connect mynet tomcat01
发现tomcat01的网络设置直接出现在了mynet的配置文件中
之后tomcat01可以直接ping通192.168网段下的所有容器