赞
踩
发布一个项目需要部署环境(Redis,ES, Hadoop……),在服务器上重新部署环境非常麻烦,不能够跨平台。
所以通过Docker用Windows全部处理完,最后再发布到Linux。
传统:开发jar,运维部署环境
现在:开发打包部署,一套流程完成
Docker为解决部署的问题提供了一套解决方案,构建镜像,部署时直接下载。
Docker通过一种隔离机制,将服务器空间运用到极致。
文档地址:https://docs.docker.com/get-started/
仓库地址:https://hub.docker.com/
docker能做什么
更加快捷的交付和部署
传统:一堆帮助文件,安装程序
Docker:打包镜像发布测试,一键运行
更快捷的升级和维护
使用Docker后,可以将项目打包成镜像,服务器A,服务器B……
更简单的系统运维
容器化使环境都高度一致
更高效的计算机资源利用
Docker是内核级虚拟化,可以运行很多容器,服务器资源可以被充分利用
镜像(Image):好比一个模版,可以通过这个模版创建容器,通过这个镜像可以创建多个容器,最终项目运行就是在容器中的
容器(Container):Docker通过容器技术,可以独立运行一个或一组。
启动、停止、删除……基本命令
仓库( repository):分为私有和共有仓库,Docker Hub默认是国外的,可以配置国内镜像
环境准备
环境查看
确定内核版本 3.10以上
[root@iZvjqtq16uz5ygZ /]# uname -r
3.10.0-957.21.3.el7.x86_64
确定系统版本为OS7
[root@iZvjqtq16uz5ygZ /]# 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/"
安装
# 删除老版本docker
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
# 设置docker镜像地址
# 阿里云版本
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 更新软件包索引
sudo yum makecache fast
# 安装docker
sudo yum install docker-ce docker-ce-cli containerd.io
# 启动docker
sudo systemctl start docker
# 查看安装成功
sudo docker version
# 测试
sudo docker run hello-world
# 查看镜像
sudo docker images
卸载
sudo yum remove docker-ce docker-ce-cli containerd.io
sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://h3j2f7ww.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
2.3 回顾hello-world
执行顺序
docker是cs结构的,通过客户端请求守护进程
docker为什么比vm快
docker version # 版本信息
docker info # docker容器信息,包括镜像和容器的数量
docker 命令 --help # 帮助命令
[root@iZvjqtq16uz5ygZ ~]# 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 查看全部
-q 只显示id
-f 筛选
[root@iZvjqtq16uz5ygZ ~]# docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 11273 [OK]
mariadb MariaDB Server is a high performing open sou… 4279 [OK]
mysql/mysql-server Optimized MySQL Server Docker images. Create… 836 [OK]
# 参数
-f 筛选
--filter=STARS=3000 # 搜索3000收藏以上的
[root@iZvjqtq16uz5ygZ ~]# docker search mysql --filter=stars=3000
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 11273 [OK]
mariadb MariaDB Server is a high performing open sou… 4279 [OK]
# 通过镜像名下载
[root@iZvjqtq16uz5ygZ ~]# docker pull mysql
Using default tag: latest # 不指定版本默认下载最新
latest: Pulling from library/mysql
33847f680f63: Pull complete # 分层下载
5cb67864e624: Pull complete
1a2b594783f5: Pull complete
b30e406dd925: Pull complete
48901e306e4c: Pull complete
603d2b7147fd: Pull complete
802aa684c1c4: Pull complete
715d3c143a06: Pull complete
6978e1b7a511: Pull complete
f0d78b0ac1be: Pull complete
35a94d251ed1: Pull complete
36f75719b1a9: Pull complete
Digest: sha256:8b928a5117cf5c2238c7a09cd28c2e801ac98f91c3f8203a8938ae51f14700fd # 签名
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest # 真实地址
# 等价
docker pull mysql
docker pull docker.io/library/mysql:latest
# 通过镜像名并指定版本
[root@iZvjqtq16uz5ygZ ~]# docker pull mysql:5.7
5.7: Pulling from library/mysql
33847f680f63: Already exists # 已经存在的不会下载
5cb67864e624: Already exists
1a2b594783f5: Already exists
b30e406dd925: Already exists
48901e306e4c: Already exists
603d2b7147fd: Already exists
802aa684c1c4: Already exists
5b5a19178915: Pull complete
f9ce7411c6e4: Pull complete
f51f6977d9b2: Pull complete
aeb6b16ce012: Pull complete
Digest: sha256:be70d18aedc37927293e7947c8de41ae6490ecd4c79df1db40d1b5b5af7d9596
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7
# 根据id或名称删除
[root@iZvjqtq16uz5ygZ ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql 5.7 8cf625070931 3 weeks ago 448MB
mysql latest c60d96bd2b77 3 weeks ago 514MB
hello-world latest d1165f221234 5 months ago 13.3kB
[root@iZvjqtq16uz5ygZ ~]# docker rmi -f 8cf625070931
Untagged: mysql:5.7
Untagged: mysql@sha256:be70d18aedc37927293e7947c8de41ae6490ecd4c79df1db40d1b5b5af7d9596
Deleted: sha256:8cf6250709314f2fcd2669e8643f5d3bdebfe715bddb63990c8c96e5d261d6fc
Deleted: sha256:452fe6896278c26338d547f8d1092011d923785247c46629b374d3477fe28c84
Deleted: sha256:bd40bf60af5d06e6b93eaf5a648393d97f70998faa3bfa1b85af55b5a270cb35
Deleted: sha256:c43e9e7d1e833650e0ed54be969d6410efa4e7fa6e27a236a44a2b97e412ee93
Deleted: sha256:70f18560bbf492ddb2eadbc511c58c4d01e51e8f5af237e3dbb319632f16335b
[root@iZvjqtq16uz5ygZ ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql latest c60d96bd2b77 3 weeks ago 514MB
hello-world latest d1165f221234 5 months ago 13.3kB
# 删除所有镜像
[root@iZvjqtq16uz5ygZ ~]# docker rmi -f $(docker images -aq)
Untagged: mysql:latest
Untagged: mysql@sha256:8b928a5117cf5c2238c7a09cd28c2e801ac98f91c3f8203a8938ae51f14700fd
Deleted: sha256:c60d96bd2b771a8e3cae776e02e55ae914a6641139d963defeb3c93388f61707
Deleted: sha256:5c8c91273faab368a6d659156f2569fa9f40b0e0139222fdf9eef073df4b3797
Deleted: sha256:33d8196a776f42a16f10395b66f10f91443b1fb194bca2a9b8dfb0deff5babb8
Deleted: sha256:3ec63323025213e3cabf17ac7933506dc5520ec49226a9764418f77ea60d35c8
Deleted: sha256:1f129b005b51b049ac84ed0775b82096d480b7d9308a9a137697f37346562266
Deleted: sha256:80ed209bd0434faa1ce31fbaab8508124dddf8f6502c5736ee4b8e46697a8477
Deleted: sha256:e53f0d35c77064014a5c1c1332d84d5f421a58418ca9c208bc470691c0e483e3
Deleted: sha256:75209fb28131d5537e73406ff0f6f508f3eb1f4d86c43d1d16df76fd28b9cc35
Deleted: sha256:34a01bee1a62a01034ffc3da48a3cb45716a0cf2e264c26663e02288e81c7ec2
Deleted: sha256:9f8bca37a56017fd3462d4fc329b0b20f97c2dd4c15e55a8e6ad1c023ab5552b
Deleted: sha256:c8a6e3f9a2412c28cd8c48e2c7bed5e7fbaa0ab6649add2dbe8641cb29b967f6
Deleted: sha256:0a26eacdbd862e75d064d817e8a5bcf5e060c2680c10f77ffa52757c0b8c3328
Deleted: sha256:814bff7343242acfd20a2c841e041dd57c50f0cf844d4abd2329f78b992197f4
Untagged: hello-world:latest
Untagged: hello-world@sha256:776b0895d5e2fcd5e80bcdd607adc45461ba11143ef3df531174bf00679f43fe
Deleted: sha256:d1165f2212346b2bab48cb01c1e39ee8ad1be46b87873d9ca7a4e434980a7726
[root@iZvjqtq16uz5ygZ ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
常用的命令
port # 查看映射端口对应的容器内部源端口
pause # 暂停容器
ps # 猎户容器列表
pull # 从docker镜像源服务器拉取指定镜像或者库镜像
push # 推送指定镜像或者库镜像至docker源服务器
restart # 重启运行的容器
rm # 移除一个或多个容器
rmi # 移除一个或多个镜像 (无容器使用该镜像才可删除,否则需要删除相关容器才可继续或 -f 强制删除)
run # 创建一个新的容器并运行一个命令
save # 保存一个镜像为一个 tar 包【对应 load】
search # 在 docker hub 中搜索镜像
start # 启动容器
stop # 停止容器
tag # 给源中镜像打标签
top # 查看容器中运行的进程信息
unpause # 取消暂停容器
version # 查看 docker版本号
wait # 截取容器停止时的退出状态值
有了镜像才可以创建容器,我们先下载centos镜像来学习
[root@iZvjqtq16uz5ygZ ~]# docker pull centos
docker run [可选参数] image
# 参数
--name="Name" 容器字,用于区分容器
-d 后台运行
-it 使用交互方式运行,进入容器查看内容
-p 指定容器端口 -p 8080:8080
-p ip:主机端口:容器端口
-p 主机端口:容器端口(常用)
-p 容器端口
容器端口
-P 随机指定端口
# 测试,启动并进入容器
# 主机名就是镜像id
[root@iZvjqtq16uz5ygZ ~]# docker run -it centos /bin/bash
[root@a59a9d04ad2c /]#
[root@a59a9d04ad2c /]# ls # 容器内的centos版本很多命令不完善
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
[root@a59a9d04ad2c /]# exit # 停止并退出
exit
[root@iZvjqtq16uz5ygZ ~]#
# docker ps 命令
# 显示正在运行的容器
# 参数
-a # 显示正在运行的+曾经运行的
-n=? # 显示最近运行的
-q # 只显示容器编号
[root@iZvjqtq16uz5ygZ ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@iZvjqtq16uz5ygZ ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a59a9d04ad2c centos "/bin/bash" 3 minutes ago Exited (0) 48 seconds ago inspiring_allen
61d006a19cdb centos "/bin/bash" 3 minutes ago Exited (0) 3 minutes ago awesome_elbakyan
8312aad0f6c6 d1165f221234 "/hello" 4 days ago Exited (0) 4 days ago recursing_banzai
# 停止并退出
exit
# 不停止退出
ctrl + P + Q
# 删除指定容器(不能删除正在运行的容器,如果要删除加 -f)
docker rm 容器id
# 删除所有容器
docker rm $(docker ps -aq)
docker ps -a -q|xargs docker rm
docker start 容器id # 启动容器
docker stop 容器id # 停止容器
docker restart 容器id # 重启容器
docker kill 容器id # 强制停止容器
后台运行容器
# 命令:docker run -d 容器
# 问题docker ps 发现没有容器
# 常见的坑:docker容器使用后台运行,必须有一个前台进程,docker发现没有应用就会停止
# nigix:容器启动后发现自己没有提供服务,就是没有程序了
查看日志
# 命令:docker logs -t -f --tail 查看的条数 容器
# 参数
[root@iZvjqtq16uz5ygZ ~]# 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)
查看容器中进程信息
# 命令:docker top 容器
[root@iZvjqtq16uz5ygZ ~]# docker top fd5dcdb7e3e9
UID PID PPID C STIME TTY TIME CMD
root 21913 21893 0 23:33 pts/0 00:00:00 /bin/bash
查看容器信息
# 命令:docker inspect 容器
[root@iZvjqtq16uz5ygZ ~]# docker inspect fd5dcdb7e3e9
[
{
"Id": "fd5dcdb7e3e9897cbab2dad9724cbb6fb436187e53e316af4fe5ad6cd42a86ba",
"Created": "2021-08-18T15:33:45.889519607Z",
"Path": "/bin/bash",
"Args": [],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 21913,
"ExitCode": 0,
"Error": "",
"StartedAt": "2021-08-18T15:33:46.140591444Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:300e315adb2f96afe5f0b2780b87f28ae95231fe3bdd1e16b9ba606307728f55",
"ResolvConfPath": "/var/lib/docker/containers/fd5dcdb7e3e9897cbab2dad9724cbb6fb436187e53e316af4fe5ad6cd42a86ba/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/fd5dcdb7e3e9897cbab2dad9724cbb6fb436187e53e316af4fe5ad6cd42a86ba/hostname",
"HostsPath": "/var/lib/docker/containers/fd5dcdb7e3e9897cbab2dad9724cbb6fb436187e53e316af4fe5ad6cd42a86ba/hosts",
"LogPath": "/var/lib/docker/containers/fd5dcdb7e3e9897cbab2dad9724cbb6fb436187e53e316af4fe5ad6cd42a86ba/fd5dcdb7e3e9897cbab2dad9724cbb6fb436187e53e316af4fe5ad6cd42a86ba-json.log",
"Name": "/sharp_lichterman",
"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/61f37a5a2acff47895e36f41643be6964ccf17288d24c807117fcce5364fcd6e-init/diff:/var/lib/docker/overlay2/3d0f44460bad8c9f659010f235579de50bb06b8cd48198e90098626252e85940/diff",
"MergedDir": "/var/lib/docker/overlay2/61f37a5a2acff47895e36f41643be6964ccf17288d24c807117fcce5364fcd6e/merged",
"UpperDir": "/var/lib/docker/overlay2/61f37a5a2acff47895e36f41643be6964ccf17288d24c807117fcce5364fcd6e/diff",
"WorkDir": "/var/lib/docker/overlay2/61f37a5a2acff47895e36f41643be6964ccf17288d24c807117fcce5364fcd6e/work"
},
"Name": "overlay2"
},
"Mounts": [],
"Config": {
"Hostname": "fd5dcdb7e3e9",
"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": "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": "4f2e2f5c5d18962c52f9dc1aa9c158229ceba25218de723989ef07a00ce21182",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {},
"SandboxKey": "/var/run/docker/netns/4f2e2f5c5d18",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "b92b0c256a421f4c7f4f91fed818a4a1d99ea9602aba55763a15cfbfe94031d4",
"Gateway": "172.17.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "172.17.0.3",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"MacAddress": "02:42:ac:11:00:03",
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "d3816c025268349314dc2077d29c90f6bafeb26db39dfaff8803797ca61a0d9d",
"EndpointID": "b92b0c256a421f4c7f4f91fed818a4a1d99ea9602aba55763a15cfbfe94031d4",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.3",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:03",
"DriverOpts": null
}
}
}
}
]
进入正在运行的容器
# 命令1:docker exec -it 容器 /bin/bash
# 命令2:docker attach 容器 /bin/bash
# 第一个是进入容器后开启新的终端,可以在里面操作
# 第二个是进入容器后打开当前正在运行的终端
拷贝文件
# 命令1:docker cp 容器:容器内路径 目的主机路径
# 该命令是把容器内的内容拷贝到外面
# 命令2:docker cp 目的主机路径 容器:容器内路径
# 该命令是把外面的内容拷贝到容器内(后面还有挂载)
搜索镜像(不建议用search,建议去dockerhub去搜)
下载镜像
[root@iZvjqtq16uz5ygZ ~]# 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@iZvjqtq16uz5ygZ ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest dd34e67e3371 28 hours ago 133MB
centos latest 300e315adb2f 8 months ago 209MB
[root@iZvjqtq16uz5ygZ ~]# docker run -d --name nginx1 -p 3344:80 nginx
81e8a171d4bfbf9417e72b879fe8262b4bf010fa39139069a98be56f7039b931
[root@iZvjqtq16uz5ygZ ~]# curl localhost:3306
<!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@iZvjqtq16uz5ygZ ~]# docker rm $(docker ps -aq)
Error response from daemon: You cannot remove a running container 81e8a171d4bfbf9417e72b879fe8262b4bf010fa39139069a98be56f7039b931. Stop the container before attempting removal or force remove
Error response from daemon: You cannot remove a running container fd5dcdb7e3e9897cbab2dad9724cbb6fb436187e53e316af4fe5ad6cd42a86ba. Stop the container before attempting removal or force remove
[root@iZvjqtq16uz5ygZ ~]# docker rm -f $(docker ps -aq)
81e8a171d4bf
fd5dcdb7e3e9
[root@iZvjqtq16uz5ygZ ~]# docker exec -it nginx1 /bin/bash
root@2b266e3c6ade:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
root@2b266e3c6ade:/# cd /etc/nginx/
root@2b266e3c6ade:/etc/nginx# ls
conf.d fastcgi_params mime.types modules nginx.conf scgi_params uwsgi_params
官方使用
# docker run -it --rm tomcat:9.0
# 我们之前运行的容器关闭后都可以查到,加上 --rm 后容器关闭就会删除,一般用于测试
# 我们正常下载镜像之后再使用
[root@iZvjqtq16uz5ygZ ~]# docker pull tomcat
# 启动
[root@iZvjqtq16uz5ygZ ~]# docker run -d -p 3355:8080 --name tomcat1 tomcat
733463ab9a58c6193d80ddfe8422529e3e4ec3544ef87697bdedf948f9ec67e3
# 外网访问没有问题,但是404
# 我们进入容器查看发现webapps为空,我们把webapps.dist内所有内容复制到webapps中在查看,此时不会有404
root@733463ab9a58:/usr/local/tomcat/webapps.dist# cp -r webapps.dist/* webapps
root@733463ab9a58:/usr/local/tomcat/webapps# ls
ROOT docs examples host-manager manager
# es暴露的端口很多
# es十分占内存
# es的数据一般要放置在安全目录
# --net somenetwork ? 网络配置
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2
# 查看是否成功
{
"name" : "b432915594c4",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "VOvkXodJT7SwTGeCGdB0ng",
"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"
}
# 用docker stats查看cpu,可以看到,es占用了很大的内存
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O
b432915594c4 elasticsearch 5.73% 1.249GiB / 1.694GiB 73.72% 1.18kB / 942B 314MB / 729kB
PIDS
43
# 启动之后发现非常卡,甚至服务器都卡住了,es很消耗内存,那么如何解决呢?
# 我们先停止所有容器,对其进行内存限制
# 通过修改配置文件 -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
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于环境开发的软件,它包含某个软件所需要的所有内容。
所有应用,直接打包docker镜像,就可以直接跑起来!
如何得到镜像?
UnionFS(联合文件系统)
我们下载的时候看到的一层层就是这个!
UnionFS(联合文件系统):是一种分层\轻量级并且高性能的文件系统,他支持文件系统的修改作为一次提交来一层层叠加,同时可以将不动目录挂载到同一个虚拟文件系统下,Union文件系统是docker镜像的基础。
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件叠加起来,这样最终的文件系统就会包含所有底层的文件和目录
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这里才200M??
对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供 rootfs 就行了。由此可见对于不同的linux发行版, bootfs基本是一致的, rootfs会有差别, 因此不同的发行版可以公用bootfs。
分层的镜像
以我们的pull为例,在下载的过程中我们可以看到docker的镜像好像是在一层一层的在下载
为什么 Docker 镜像要采用这种分层结构呢
最大的一个好处就是 - 共享资源
比如:有多个镜像都从相同的 base 镜像构建而来,那么宿主机只需在磁盘上保存一份base镜像,
同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。
特点
Docker镜像都是只读的当容器启动时,一个新的可写层被加载到镜像的顶部。
这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。
docker commit 提交容器成为一个新的副本
docker commit -m="提交信息" -a="作者" 容器id 目标镜像名:[TAG]
实战测试
# 我们将官方tomcat中webapps.dist文件夹下的内容复制到webapps下(官方的不能直接运行)
# 然后exit退出镜像
# 提交我们自己的镜像
[root@iZvjqtq16uz5ygZ ~]# docker commit -m="add webapps" -a="JinWeimin" 733463ab9a58 mytomcat:1.0
sha256:d10f7bf3719ec5177044f850862d0983ca9fa550df3b3f6a0099e139ba084e40
# 此时我们自己的tomcat就已经在里面了
[root@iZvjqtq16uz5ygZ ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mytomcat 1.0 d10f7bf3719e 25 seconds ago 673MB
nginx latest dd34e67e3371 7 days ago 133MB
tomcat latest 710ec5c56683 2 weeks ago 668MB
portainer/portainer latest 580c0e4e98b0 5 months ago 79.1MB
centos latest 300e315adb2f 8 months ago 209MB
elasticsearch 7.6.2 f29a1ee41030 17 months ago 791MB
应用和环境运行在容器中,那么我们容器删除,数据就会丢失(数据库的数据等)
我们想要让这个数据可以持久化
此时需要一个容器见数据共享的技术,把数据保存在本地,Docker容器中产生的变化,同步到本地!
这就是卷技术!
目录的挂载,将我们容器内的目录,同步到本地。
总结:容器的持久化和同步操作!容器间的数据共享
方式一:通过命令挂载
docker run -it -v 主机目录:容器内目录
# 测试
# 创建容器,进行挂载
# 使用 docker inspect 查看挂载情况
# 容器 --
[root@iZvjqtq16uz5ygZ usr]# docker run -it --name="myCentos" -v /home/test:/home centos
[root@a67776510c8c ~]# cd /home
[root@a67776510c8c home]# touch test.c
# 本地 --
[root@iZvjqtq16uz5ygZ home]# cd test
[root@iZvjqtq16uz5ygZ test]# ls
test.c
# 此时可以发现挂载后,容器被挂载的文件夹所有的改动都会同步在本地挂载的文件夹
好处:我们以后修改配置等,只需要在本地修改
mysql的数据是放在data目录下的
# 安装mysql镜像
[root@iZvjqtq16uz5ygZ test]# docker pull mysql:8.0.21
# 创建容器 # 安装mysql主要要配置密码
官方:docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
# some-mysql 为容器名 tag为版本号 my-secret-pw为密码
# 在此基础上配置数据集挂载
docker run --name mysql1 \
-e MYSQL_ROOT_PASSWORD=123456 \
-d \
-p 33060:3306 \
-v /home/docker/mysql/conf:/etc/mysql/conf.d \
-v /home/docker/mysql/data:/var/lib/mysql \
mysql:8.0.21
# 启动成功后,我们用workbench连接一下这个mysql数据库
# 匿名挂载
# docker run -P -d --name nginx1 -v /etc/nginx nginx
# 查看所有卷的情况
# docker volume ls
[root@iZvjqtq16uz5ygZ conf]# docker volume ls
DRIVER VOLUME NAME
local 06e0151f0bd1ce53e9a3b105f3fa8e99fa0c068da523ab50028881420ff6ada4
local 637afa56c8ed6519a0b1e46b4ae564aed10042cd295cded5c7f5f8eff231033b
# 这种就是匿名挂载
# 具名挂载
# docker run -P -d --name nginx2 -v jumingnginx:/etc/nginx nginx
# 查看卷的情况
[root@iZvjqtq16uz5ygZ conf]# docker volume ls
DRIVER VOLUME NAME
local jumingnginx
# 此时就是具名挂载
所有docker容器内的卷在没有指定目录时都是在 ‘/var/lib/docker/volumes/xxxxxx/_data’ 下
我们通过具名挂载可以方便的找到我们的卷
如何确定是匿名挂载还是具名挂载还是指定路径挂载?
-v 容器内路径 # 匿名挂载
-v 卷名:容器内路径 # 具名挂载
-v 容器外路径:容器内路径 # 指定路径挂载
# 拓展
# 在容器内路径后加上ro/rw改变读写权限
docker run -P -d --name nginx2 -v jumingnginx:/etc/nginx:ro nginx # 只读
docker run -P -d --name nginx2 -v jumingnginx:/etc/nginx:rw nginx # 可读写
# 只要有ro,就只能通过宿主机修改,无法通过容积修改
我们也可以通过DockerFile构建数据卷
DockerFile就是用来构建镜像的脚本
镜像是一层一层的,脚本一个个的命令,就是一层层镜像
我们先简单在 /home/docker-test 目录下编写一个简单的DockerFile文件
# /home/docker-test/dockerFile1
# 文件内容: 命令 参数
FROM centos
VOLUME ["volume1","volume2"]
CMD echo "----end----"
CMD /bin/bash
# 每一行命令就是镜像的一层
通过这个文件构建镜像
# -f dockerFile的路径
# -t 镜像名称
[root@iZvjqtq16uz5ygZ docker-volume]# docker build -f ./dockerFile1 -t test/image .
Sending build context to Docker daemon 2.048kB
Step 1/4 : FROM centos
---> 300e315adb2f
Step 2/4 : VOLUME ["volume1","volume2"]
---> Using cache
---> 334c4fdb5982
Step 3/4 : CMD echo "----end----"
---> Using cache
---> c09b17886130
Step 4/4 : CMD /bin/bash
---> Using cache
---> 671b3b46a050
Successfully built 671b3b46a050
Successfully tagged test/image:latest
[root@iZvjqtq16uz5ygZ docker-volume]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
test/image latest 671b3b46a050 11 minutes ago 209MB # 这就是我们创建的镜像
mytomcat 1.0 d10f7bf3719e 2 days ago 673MB
nginx latest dd34e67e3371 10 days ago 133MB
tomcat latest 710ec5c56683 2 weeks ago 668MB
centos latest 300e315adb2f 8 months ago 209MB
mysql 8.0.21 8e85dd5c3255 10 months ago 544MB
elasticsearch 7.6.2 f29a1ee41030 17 months ago 791MB
我们通过这个镜像新建容器
[root@iZvjqtq16uz5ygZ docker-volume]# docker run -it 671b3b46a050 /bin/bash
[root@732c2589347e /]# ls -lah
total 64K
drwxr-xr-x 1 root root 4.0K Aug 27 15:41 .
drwxr-xr-x 1 root root 4.0K Aug 27 15:41 ..
-rwxr-xr-x 1 root root 0 Aug 27 15:41 .dockerenv
lrwxrwxrwx 1 root root 7 Nov 3 2020 bin -> usr/bin
drwxr-xr-x 5 root root 360 Aug 27 15:41 dev
drwxr-xr-x 1 root root 4.0K Aug 27 15:41 etc
drwxr-xr-x 2 root root 4.0K Nov 3 2020 home
lrwxrwxrwx 1 root root 7 Nov 3 2020 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Nov 3 2020 lib64 -> usr/lib64
drwx------ 2 root root 4.0K Dec 4 2020 lost+found
drwxr-xr-x 2 root root 4.0K Nov 3 2020 media
drwxr-xr-x 2 root root 4.0K Nov 3 2020 mnt
drwxr-xr-x 2 root root 4.0K Nov 3 2020 opt
dr-xr-xr-x 104 root root 0 Aug 27 15:41 proc
dr-xr-x--- 2 root root 4.0K Dec 4 2020 root
drwxr-xr-x 11 root root 4.0K Dec 4 2020 run
lrwxrwxrwx 1 root root 8 Nov 3 2020 sbin -> usr/sbin
drwxr-xr-x 2 root root 4.0K Nov 3 2020 srv
dr-xr-xr-x 13 root root 0 Aug 27 15:41 sys
drwxrwxrwt 7 root root 4.0K Dec 4 2020 tmp
drwxr-xr-x 12 root root 4.0K Dec 4 2020 usr
drwxr-xr-x 20 root root 4.0K Dec 4 2020 var
drwxr-xr-x 2 root root 4.0K Aug 27 15:41 volume1 # 这里发现volume1和volume2
drwxr-xr-x 2 root root 4.0K Aug 27 15:41 volume2 # 说明volume1和volume2已经被挂载了
由于我们在dockerFile中没有指定volume的名称,说明这是一个匿名挂载,挂载的文件夹也在默认目录下
这种创建数据卷的方式是我们常用的方式
构建容器时 --volumes-from参数 可以让容器使用相同的容器数据卷
我们可能会想让多个容器的数据同步,比如mysql数据同步
我们先创建一个我们自己镜像的容器
# docker01(数据卷容器)
[root@iZvjqtq16uz5ygZ docker-volume]# docker run -it --name docker01 671b3b46a050 /bin/bash
[root@745b1830cc3a /]# ls -lah
total 64K
drwxr-xr-x 1 root root 4.0K Aug 27 15:59 .
drwxr-xr-x 1 root root 4.0K Aug 27 15:59 ..
-rwxr-xr-x 1 root root 0 Aug 27 15:59 .dockerenv
lrwxrwxrwx 1 root root 7 Nov 3 2020 bin -> usr/bin
drwxr-xr-x 5 root root 360 Aug 27 15:59 dev
drwxr-xr-x 1 root root 4.0K Aug 27 15:59 etc
drwxr-xr-x 2 root root 4.0K Nov 3 2020 home
lrwxrwxrwx 1 root root 7 Nov 3 2020 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Nov 3 2020 lib64 -> usr/lib64
drwx------ 2 root root 4.0K Dec 4 2020 lost+found
drwxr-xr-x 2 root root 4.0K Nov 3 2020 media
drwxr-xr-x 2 root root 4.0K Nov 3 2020 mnt
drwxr-xr-x 2 root root 4.0K Nov 3 2020 opt
dr-xr-xr-x 106 root root 0 Aug 27 15:59 proc
dr-xr-x--- 2 root root 4.0K Dec 4 2020 root
drwxr-xr-x 11 root root 4.0K Dec 4 2020 run
lrwxrwxrwx 1 root root 8 Nov 3 2020 sbin -> usr/sbin
drwxr-xr-x 2 root root 4.0K Nov 3 2020 srv
dr-xr-xr-x 13 root root 0 Aug 27 15:41 sys
drwxrwxrwt 7 root root 4.0K Dec 4 2020 tmp
drwxr-xr-x 12 root root 4.0K Dec 4 2020 usr
drwxr-xr-x 20 root root 4.0K Dec 4 2020 var
drwxr-xr-x 2 root root 4.0K Aug 27 15:59 volume1
drwxr-xr-x 2 root root 4.0K Aug 27 15:59 volume2
然后创建第二个和第三个容器,使用 --volumes-from 实现数据同步
docker run -it --name docker02 --volumes-from 745b1830cc3a 671b3b46a050 /bin/bash
docker run -it --name docker03 --volumes-from 745b1830cc3a 671b3b46a050 /bin/bash
我们通过 docker inspect发现,此时这三个容器挂载的目录是一样的,也就是说,他们共享一个数据卷
在三个容器任意一个中的被挂载的文件夹中修改数据,其他的都会产生相同的效果
实际上它们被挂载的部分使用的都是本机上的同一块地址,也就是volume默认的地址
此时删除任何一个容器,都不会影响到其他的容器
此时就做到了数据共享
多个mysql实现数据共享
# 第一个mysql容器
docker run --name mysql1 \
-e MYSQL_ROOT_PASSWORD=123456 \
--name mysql01 \
-d \
-p 33060:3306 \
-v /etc/mysql/conf.d \
-v /var/lib/mysql \
mysql
# 第二个mysql容器
docker run --name mysql1 \
-e MYSQL_ROOT_PASSWORD=123456 \
--name mysql02 \
-d \
-p 33061:3306 \
--volumes-from mysql01 \
mysql
dockerFile就是用来构建镜像的文件
构建步骤:
基础知识:
指令 | 作用 |
---|---|
FROM | 基础镜像,镜像的构建基于这个基础镜像 |
MAINTAINER(deprecate) | 镜像是谁写的 |
LABEL | 添加原数据到镜像 |
RUN | 镜像构建时所需要执行的命令 |
ADD | 要添加的内容——比如要添加一个tomcat,就需要ADDcomcat的压缩包 |
WORKDIR | 镜像的工作目录 |
VOLUME | 挂载的目录 |
EXPOSE | 暴露的端口设置(随机映射) |
CMD | 指定容器启动时需要执行的命令,只有最后一个会生效,可被替代 |
ENTRYPOINT | 指定容器启动时需要执行的命令,可以追加命令 |
ONBUILD | 当构建一个被继承docker file,这个时候ONBUILD会被执行 |
COPY | 类似ADD,将文件拷贝到镜像中 |
ENV | 构建时设置环境变量 |
Docker中绝大多数的镜像都是FROM scratch
创建一个自己的centos
FROM centos
ENV MYPATH /usr/local
WORKDIR $MYPATH
LABEL "maintainer"="JinWeimin"
RUN yum install -y vim
RUN yum install -y net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "--end--"
CMD /bin/bash
# -f dockerFile的路径
# -t 镜像名称
docker build -f ./my-centos-docker-file -t my-centos:1.0 .
我们可以通过 docker history查看镜像的构建历史
创建tomcat
Dockerfile
为文件名,此时不需要指定-fDockerhub
登陆自己的dockerhub账号
docker login -u 123456
推送镜像
# 先给镜像重新起个名
docker tag my-tomcat jin/my-tomcat:1.0
# 推送镜像
docker push jin/my-tomcat:1.0
阿里云
登陆阿里云
找到镜像仓库
创建命名空间
创建容器镜像
按照阿里云里面的命令推送
docker0就是个默认的网卡
docker每创建一个容器就会新创建一对网卡,容器通过与docker0桥接(bridge模式)来互相访问
linux系统再通过NAT(网络地址转换)访问到 eth0网卡进行与internet互联
查看所有的网络
docker network ls
网络模式:
测试:
# 我们新建容器时默认使用docker0
docker run -d -P --net bridge tomcat
创建
docker network create --subnet 192.168.0.0/16 --gateway 255.255.0.0 mynet
不同网络正常是不能互相访问的的,所以我们要连接网络
# 这里的mynet是我们自定义的网络,tomcat是默认网络下的一个容器
docker network connect mynet tomcat
# 连接之后我们就可以让tomcat访问mynet里面的容器了
FROM java:8
COPY *.jar /app.jar
CMD ["--server.port=8080"]
EXPOSE 8080
ENTRYPOINT [ "java" , "-jar" , " / app.jar"]
构建镜像
发布运行
IDEA插件 -> docker
mkdir composedir
cd composedir
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)
flask
redis
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"]
version: "3.0"
services:
web:
build: .
ports:
- "5000:5000"
redis:
image: "redis:alpine"
docker-compose up
docker-compose运行流程
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。