[root@localhost ~]# systemctl start docker
[root@localhost ~]# docker --help
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql 5.7 c20987f18b13 5 months ago 448MB
mysql latest 3218b38490ce 5 months ago 516MB
hello-world latest feb5d9fea6a5 7 months ago 13.3kB
[root@localhost ~]# docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 12606 [OK]
mariadb MariaDB Server is a high performing open sou… 4843 [OK]
percona Percona Server is a fork of the MySQL relati… 576 [OK]
phpmyadmin phpMyAdmin - A web interface for MySQL and M… 542 [OK]
bitnami/mysql Bitnami MySQL Docker Image 71 [OK]
linuxserver/mysql-workbench 36
linuxserver/mysql A Mysql container, brought to you by LinuxSe… 35
ubuntu/mysql MySQL open source fast, stable, multi-thread… 33
circleci/mysql MySQL is a widely used, open-source relation… 26
google/mysql MySQL server for Google Compute Engine 21 [OK]
rapidfort/mysql RapidFort optimized, hardened image for mysql 12
vmware/harbor-db Mysql container for Harbor 10
bitnami/mysqld-exporter 3
ibmcom/mysql-s390x Docker image for mysql-s390x 2
nasqueron/mysql 1 [OK]
newrelic/mysql-plugin New Relic Plugin for monitoring MySQL databa… 1 [OK]
vitess/mysqlctld vitess/mysqlctld 1 [OK]
cimg/mysql 0
mirantis/mysql 0
drud/mysql-local-57 ddev mysql local container 0
drud/mysql-docker-local-57 This repo has been deprecated, new tags are … 0
drud/mysql 0
drud/mysql-docker-local docker containers for local womysql rk 0 [OK]
docksal/mysql MySQL service images for Docksal - https://d… 0
silintl/mysql-backup-restore Simple docker image to perform mysql backups… 0 [OK]
[root@localhost ~]# docker pull mysql
Using default tag: latest # 如果不写tag. 默认就是latest
latest: Pulling from library/mysql
72a69066d2fe: Pull complete # 分层下载,docker imager 的核心 联合文件系统
93619dbc5b36: Pull complete
99da31dd6142: Pull complete
626033c43d70: Pull complete
37d5d7efb64e: Pull complete
ac563158d721: Pull complete
d2ba16033dad: Pull complete
688ba7d5c01a: Pull complete
00e060b6d11d: Pull complete
1c04857f594f: Pull complete
4d7cfa90e6ea: Pull complete
e0431212d27d: Pull complete
Digest: sha256:e9027fe4d91c0153429607251656806cc784e914937271037f7738bd5b8e7709 #签名
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest #真实地址
# 等价于它 以下命令等价
docker pull mysql
docker pull docker.io/library/mysql:latest
# 指定版本下载
[root@localhost ~]# docker pull mysql:5.7
5.7: Pulling from library/mysql
72a69066d2fe: Already exists #上面已经下载过的mysql镜像,这一次可以共用,所以表示已存在
93619dbc5b36: Already exists
99da31dd6142: Already exists
626033c43d70: Already exists
37d5d7efb64e: Already exists
ac563158d721: Already exists
d2ba16033dad: Already exists
0ceb82207cd7: Pull complete
37f2405cae96: Pull complete
e2482e017e53: Pull complete
70deed891d42: Pull complete
Digest: sha256:f2ad209efe9c67104167fc609cca6973c8422939491c9345270175a300419f94
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7
# 查看已有的镜像
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql 5.7 c20987f18b13 5 months ago 448MB
mysql latest 3218b38490ce 5 months ago 516MB
hello-world latest feb5d9fea6a5 7 months ago 13.3kB
# 根据镜像的id进行删除
[root@localhost ~]# docker rmi -f c20987f18b13
Untagged: mysql:5.7
Untagged: mysql@sha256:f2ad209efe9c67104167fc609cca6973c8422939491c9345270175a300419f94
Deleted: sha256:c20987f18b130f9d144c9828df630417e2a9523148930dc3963e9d0dab302a76
Deleted: sha256:6567396b065ee734fb2dbb80c8923324a778426dfd01969f091f1ab2d52c7989
# 查看镜像,删除成功
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql latest 3218b38490ce 5 months ago 516MB
hello-world latest feb5d9fea6a5 7 months ago 13.3kB
# 查询出所有镜像后进行递归删除
[root@localhost ~]# docker rmi -f $(docker images -aq)
Untagged: mysql:latest
Untagged: mysql@sha256:e9027fe4d91c0153429607251656806cc784e914937271037f7738bd5b8e7709
Deleted: sha256:3218b38490cec8d31976a40b92e09d61377359eab878db49f025e5d464367f3b
Untagged: hello-world:latest
Untagged: hello-world@sha256:80f31da1ac7b312ba29d65080fddf797dd76acfb870e677f390d5acba9741b17
Deleted: sha256:feb5d9fea6a5e9606aa995e879d862b825965ba48de054caab5ef356dc6b3412
说明:我们有了镜像才可以创建容器,linux,下载一个centos镜像来测试学习
[root@localhost ~]# docker pull centos
Using default tag: latest
latest: Pulling from library/centos
# 查看镜像, 镜像已经下载成功
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos latest 5d0da3dc9764 8 months ago 231MB
docker run [可选参数] image # 可选参数使用 docker run --help 命令查看有哪些
# 参数说明
--name="name" 容器名字 tomcat01 tomcat02 用来区分容器
-d 后台方式运行
-it 使用交互方式运行,进入容器查看内容
-p 指定容器的端口 -p 8080:8080\
-p 主机端口:容器端口(常用)
-p 容器端口
-p 随机指定端口
[root@localhost ~]# docker run -it centos /bin/bash
[root@317beaac0681 /]#
[root@317beaac0681 /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
exit # 容器停止运行并退出
ctrl + p + q # 容器不停止退出
[root@317beaac0681 /]# exit # 容器停止运行并退出
# ctrl + P + Q # 容器不停止退出 (在键盘的大写模式下按这几个键)
[root@4cac2196aa2e /]# [root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4cac2196aa2e centos "/bin/bash" 13 seconds ago Up 10 seconds peaceful_carver
64efab6e12e5 centos "/bin/bash" About a minute ago Up About a minute objective_jackson
# docker ps 命令
-a # 列出当前正在运行的容器(默认容器),顺带带出历史运行过的容器
-n=? # 只显示最近创建的容器
-q # 只显示容器的编号
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3bd0aed6e189 centos "/bin/bash" 45 seconds ago Exited (0) 17 seconds ago hopeful_williams
598addfa8720 centos "/bin/bash" 5 hours ago Exited (0) 5 hours ago quirky_agnesi
317beaac0681 centos "/bin/bash" 5 hours ago Exited (130) 5 hours ago fervent_lalande
83c174518303 feb5d9fea6a5 "/hello" 46 hours ago Exited (0) 46 hours ago thirsty_davinci
204a0f5e6da0 feb5d9fea6a5 "/hello" 46 hours ago Exited (0) 46 hours ago clever_archimedes
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4cac2196aa2e centos "/bin/bash" 13 seconds ago Up 10 seconds peaceful_carver
64efab6e12e5 centos "/bin/bash" About a minute ago Up About a minute objective_jackson
docker rm 容器id # 根据容器id删除容器(不能删除正在运行的容器,要强制删除利用 rm -f)
docker rm -f $(docker ps -aq) # 删除所有容器
docker ps -a -q|xargs docker rm # 删除所有容器
下面是列子:
# 由于rm 容器id 不能删除正在运行的容器而导致报错
[root@localhost ~]# docker rm 4cac2196aa2e
Error response from daemon: You cannot remove a running container 4cac2196aa2e1df5d16f987c560d3dd81dea7cfa1bdb362cc4e4150856421d0b. Stop the container before attempting removal or force remove
[root@localhost ~]# docker ps -aq
4cac2196aa2e
64efab6e12e5
3bd0aed6e189
598addfa8720
317beaac0681
83c174518303
204a0f5e6da0
# rm -f 即可删除正在运行的容器 $(docker ps -aq): 查询出所有正在运行的容器
[root@localhost ~]# docker rm -f $(docker ps -aq)
4cac2196aa2e
64efab6e12e5
3bd0aed6e189
598addfa8720
317beaac0681
83c174518303
204a0f5e6da0
[root@localhost ~]# docker ps -aq
[root@localhost ~]# # 可以看到,容器都被删除掉了
docker start 容器id # 启动容器
docker restart 容器id # 重启容器
docker stop 容器id # 停止 当前正在运行的容器
docker kill # 强制停止当前容器
下面是例子(需要有历史运行过的容器,才可以使用以上四条命令):
# 先运行一个容器(这里的目的为了能找到历史运行容器id,否则无法使用上面的方式启动容器)
[root@localhost ~]# docker run -it centos /bin/bash
# 把该容器退出
[root@00faae8b4bf2 /]# exit
exit
# 查看当前正在运行的容器(为空)
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# 查看历史运行过的容器(可以看到 容器id=00faae8b4bf2。有了该容器id 就可以用以上命令启动或者停止容器了)
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
00faae8b4bf2 centos "/bin/bash" 19 seconds ago Exited (127) 8 seconds ago suspicious_meninsky
1581a1d0cf0a centos "/bin/bash" About a minute ago Exited (0) About a minute ago serene_bouman
# 使用docker start 容器id 命令启动容器
[root@localhost ~]# docker start 00faae8b4bf2
00faae8b4bf2
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
00faae8b4bf2 centos "/bin/bash" 45 seconds ago Up 4 seconds suspicious_meninsky
# 使用docker stop 容器id 停止容器
[root@localhost ~]# docker stop 00faae8b4bf2
00faae8b4bf2
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@localhost ~]#
注意: 该条命令启动容器后,使用docker ps 查看,会发现该容器停止了
原因: docker 容器使用后台运行,就必须要有一个前台的进程,docker 发现没有应用,就会自动停止
有使用容器就装了一个nginx ,此时容器启动后,发现自己没有提供服务,就会立刻停止,就是没有程序了
# docker run -d 镜像名
docker logs -f -t --tail [要显示的日志条数] 容器id
# 自己编写一段shell脚本,循环打印一句话(为了查看日志)
[root@localhost ~]# docker run -d centos /bin/sh -c "while true;do echo chenxiansheng;sleep 1;done"
3926294a2cca4431540e8c5aced519f22c0999f9e6466bd96e767cea548c53ae
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3926294a2cca centos "/bin/sh -c 'while t…" 5 seconds ago Up 4 seconds fervent_torvalds
# 查看日志命令
[root@localhost ~]# docker logs -t -f --tail 5 3926294a2cca
2022-05-22T06:56:16.970217803Z chenxiansheng
2022-05-22T06:56:17.983250772Z chenxiansheng
2022-05-22T06:56:18.994815474Z chenxiansheng
2022-05-22T06:56:19.998974466Z chenxiansheng
2022-05-22T06:56:21.003155944Z chenxiansheng
^C
[root@localhost ~]#
docker top 容器id
# 例子:
[root@localhost ~]# docker top 3926294a2cca
UID PID PPID C STIME TTY TIME CMD
root 1967 1947 0 14:54 ? 00:00:00 /bin/sh -c while true;do echo chenxiansheng;sleep 1;done
root 2845 1967 0 15:08 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1
docker inspect
# docker inspect 能使用的命令
[root@localhost ~]# docker inspect --help
Usage: docker inspect [OPTIONS] NAME|ID [NAME|ID...]
Return low-level information on Docker objects
Options:
-f, --format string Format the output using the given Go template
-s, --size Display total file sizes if the type is container
--type string Return JSON for specified type
下面是使用例子:
# 可以看到镜像id 是该进程id的前缀
[root@localhost ~]# docker inspect 3926294a2cca
[
{
"Id": "3926294a2cca4431540e8c5aced519f22c0999f9e6466bd96e767cea548c53ae",
"Created": "2022-05-22T06:54:51.055490626Z",
"Path": "/bin/sh",
"Args": [
"-c",
"while true;do echo chenxiansheng;sleep 1;done"
],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 1967,
"ExitCode": 0,
"Error": "",
"StartedAt": "2022-05-22T06:54:52.152158173Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6",
"ResolvConfPath": "/var/lib/docker/containers/3926294a2cca4431540e8c5aced519f22c0999f9e6466bd96e767cea548c53ae/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/3926294a2cca4431540e8c5aced519f22c0999f9e6466bd96e767cea548c53ae/hostname",
"HostsPath": "/var/lib/docker/containers/3926294a2cca4431540e8c5aced519f22c0999f9e6466bd96e767cea548c53ae/hosts",
"LogPath": "/var/lib/docker/containers/3926294a2cca4431540e8c5aced519f22c0999f9e6466bd96e767cea548c53ae/3926294a2cca4431540e8c5aced519f22c0999f9e6466bd96e767cea548c53ae-json.log",
"Name": "/fervent_torvalds",
"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/e564fca82acaf0d594fea6217e190503e5674ff9909a45429ec75cb0d8ab2d72-init/diff:/var/lib/docker/overlay2/8da0b0258a4c475bbdf2c544b058908a98b9e203ccddd77c36dcad7dc096162a/diff",
"MergedDir": "/var/lib/docker/overlay2/e564fca82acaf0d594fea6217e190503e5674ff9909a45429ec75cb0d8ab2d72/merged",
"UpperDir": "/var/lib/docker/overlay2/e564fca82acaf0d594fea6217e190503e5674ff9909a45429ec75cb0d8ab2d72/diff",
"WorkDir": "/var/lib/docker/overlay2/e564fca82acaf0d594fea6217e190503e5674ff9909a45429ec75cb0d8ab2d72/work"
},
"Name": "overlay2"
},
"Mounts": [],
"Config": {
"Hostname": "3926294a2cca",
"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 chenxiansheng;sleep 1;done"
],
"Image": "centos",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {
"org.label-schema.build-date": "20210915",
"org.label-schema.license": "GPLv2",
"org.label-schema.name": "CentOS Base Image",
"org.label-schema.schema-version": "1.0",
"org.label-schema.vendor": "CentOS"
}
},
"NetworkSettings": {
"Bridge": "",
"SandboxID": "d80dfcd35589cac557f556bf5f47895d0d7dc9eabf461985c703b240daed0f33",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {},
"SandboxKey": "/var/run/docker/netns/d80dfcd35589",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "41234855c20dd7890acb5e3a48217c14e61a1e3ab876d01f79ed03b88d543b88",
"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": "5702770d4ed5c8618623571e5e7d4fa386b63c152a28bc01c40830bb8e389d21",
"EndpointID": "41234855c20dd7890acb5e3a48217c14e61a1e3ab876d01f79ed03b88d543b88",
"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
}
}
}
}
]
docker exec -it 容器id bashShell # 进入容器后开启一个新的终端,可以再里面操作
docker attach 容器id # 进入容器正在执行的终端,不会开启新的进程
-it # 表示使用交互模式
下面是例子
[root@localhost ~]# docker exec -it 3926294a2cca /bin/bash
[root@3926294a2cca /]#
docker cp 容器id:容器内路径 目的主机路径
下面是例子: 首先进入到容器home文件夹建立一个文件,随后退出到本机,再利用docker复制命令把容器的文件复制到本机的home里面来
[root@localhost ~]# docker exec -it 3926294a2cca /bin/bash
[root@3926294a2cca /]# cd home
[root@3926294a2cca home]#
[root@3926294a2cca home]# touch chenxiansheng222.java
[root@3926294a2cca home]# ls
chenxiansheng222.java
[root@3926294a2cca home]# exit
exit
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3926294a2cca centos "/bin/sh -c 'while t…" 35 minutes ago Up 35 minutes fervent_torvalds
47d1e769d463 centos "/bin/sh -c 'while t…" 36 minutes ago Exited (137) 35 minutes ago great_wing
00faae8b4bf2 centos "/bin/bash" 18 hours ago Exited (0) 18 hours ago suspicious_meninsky
1581a1d0cf0a centos "/bin/bash" 18 hours ago Exited (0) 18 hours ago serene_bouman
# 使用复制命令将容器的文件复制到本机的linux上来
[root@localhost ~]# docker cp 3926294a2cca:/home/chenxiansheng222.java /home
[root@3926294a2cca home]# exit
exit
[root@localhost /]# cd home/
[root@localhost home]# ls
chenmaolin chenxiansheng222.java # 可以看到文件已经正确复制到本机上了
1、 下载nginx 镜像
2、 启动nginx
3、测试
docker run -d --name nginx01 -p 3344:80 nginx
- -d # 设置后台运行
- –name nginx01 # 给要启动的nginx一个名字,取名为nginx01
- -p 3344:80 # 3344指的是linux的端口号,80指的是nginx容器的默认端口,将容器的
# 下载nginx 镜像
[root@localhost ~]# docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
a2abf6c4d29d: Pull complete
a9edb18cadd1: Pull complete
589b7251471a: Pull complete
186b1aaa4aa6: Pull complete
b4df32aa5a72: Pull complete
a0bcbecc962e: Pull complete
Digest: sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 605c77e624dd 4 months ago 141MB
centos latest 5d0da3dc9764 8 months ago 231MB
# 运行nginx镜像,参数说明:
- -d # 设置后台运行
- --name nginx01 # 给要启动的nginx一个名字,取名为nginx01
- -p 3344:80 # 3344指的是linux的端口号,80指的是nginx容器的默认端口,将容器的端口映射到linux端口
- nginx #指的是容器名称REPOSITORY
[root@localhost ~]# docker run -d --name nginx01 -p 3344:80 nginx
e87309bccecb4163d75b0cf6d87ebadc330e64b6de14e7c31fd0a76da19f23d8
# 查看运行的nginx ,可以看到容器运行成功
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e87309bccecb nginx "/docker-entrypoint.…" 26 seconds ago Up 23 seconds 0.0.0.0:3344->80/tcp, :::3344->80/tcp nginx01
# 测试nginx,可以看到 welcome to nginx ,测试成功
[root@localhost ~]# curl localhost:3344
<!DOCTYPE html>
Welcome to nginx!</title>
HTTP Status 404 – Not Found
Type Status Report
Description The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.
Apache Tomcat/10.0.14
[root@localhost ~]# ^C
那为什么使用linux地址:3355 没有访问tomcat成功呢,明明容器已经正常启动了。
原因是因为该tomcat是阉割版本的,对应的webapps文件夹下是空的
# 进入到tomcat容器里,ls查看目录
[root@localhost ~]# docker exec -it 77a49b3e9292 /bin/bash
root@77a49b3e9292:/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
# 进入到webapps目录,发现是空目录
root@77a49b3e9292:/usr/local/tomcat# cd webapps
root@77a49b3e9292:/usr/local/tomcat/webapps# ls
root@77a49b3e9292:/usr/local/tomcat/webapps#
但是,可以看到,虽然该阉割版的tomcat的webapps目录是空的,但是对应的webapps.dist 目录却是有内容的,而里面的内容刚好是webapps文件所需要的
root@77a49b3e9292:/usr/local/tomcat# cd webapps.dist/
root@77a49b3e9292:/usr/local/tomcat/webapps.dist# ll # 由于是阉割版本,所有ll命令都没有
bash: ll: command not found
# 可以看到,webapps.dist 目录下的文件都是webapps所需要的,把它复制到webapps 目录下
root@77a49b3e9292:/usr/local/tomcat/webapps.dist# ls
ROOT docs examples host-manager manager
使用cp命令,将webapps.dist 目录下的文件拷贝到webapps 目录下,使用本机地址加3355端口号就可以成功访问tomcat了
root@77a49b3e9292:/usr/local/tomcat# cp -r webapps.dist/* webapps
root@77a49b3e9292:/usr/local/tomcat# cd webapps
root@77a49b3e9292:/usr/local/tomcat/webapps# ls
ROOT docs examples host-manager manager # webapps文件有内容了
重新使用liunx地址+3355 (前面启动tomcat容器的时候指定了映射到linux的3355端口)端口号访问:
熟悉的tomcat页面,访问成功!!!
portainer:Docker图形化界面管理工具! 提供一个后台面板供我们操作
使用下面的命令安装portainer,并把端口映射到linux的8088端口(这样就可以用linux地址+端口号访问了)
docker run -d -p 8088:9000
–restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
登陆后,选择连接本地,可以查看已有的镜像(不是重点,一般不用,了解即可):
docker commit
提交镜像命令:docker commit -a="chenxiansheng" -m="add webapps app" 77a49b3e9292 chentomcat:1.0
参数说明:
- -a="chenxiansheng" # 提交的人的标识
- -m="add webapps app" #提交的描述
- 77a49b3e9292 #容器id
- chentomcat:1.0 #设定镜像名称,并设定版本为1.0
步骤:
# 1、首先利用上面下载好的tomcat镜像,启动一个tomcat容器
# 2、然而这个默认的tomcat是没有webapps应用的,镜像的原因,官方的镜像默认webapps下面是没有文件的
# 3、把基本文件拷贝进webapps里面
# 4、将上面操作过的容器通过commit 提交为一个新的镜像,以后就可以使用自己的镜像,可以直接访问tomcat页面成功。
上面说的步骤,有不懂的,可以查看上面的docker 安装tomcat ,由于官方的tomcat是阉割版的,访问不了tomcat页面(原因是webapps目录没有文件),我们这里就把他优化一下,就是把webapps目录的文件补充完整。
# 使用cp命令,将webapps.dist 目录下的文件拷贝到webapps 目录下,使用本机地址加3355端口号就可以成功访问tomcat了
root@77a49b3e9292:/usr/local/tomcat# cp -r webapps.dist/* webapps
root@77a49b3e9292:/usr/local/tomcat# cd webapps
root@77a49b3e9292:/usr/local/tomcat/webapps# ls
ROOT docs examples host-manager manager # webapps文件有内容了
测试一下
测试没有问题,现在把这个运行的容器,提交成我们自己的镜像。以后运行就用我们自己的tomcat镜像,就不需要再做一次将webapps.dict 目录的文件拷贝到webapps目录下的操作后,才能查看tomcat页面了。
# 从刚刚启动的容器中退出来
root@77a49b3e9292:/usr/local/tomcat/webapps# exit
exit
# 使用提交镜像命令
[root@localhost ~]# docker commit -a="chenxiansheng" -m="add webapps app" 77a49b3e9292 chentomcat:1.0
sha256:8c3fc729e0f1c139d2b7b1cbe7acb2c3f12cb5c8e3cdf307dc5813fb8258c613
可以看到我们已经生成了自己的镜像了 chentomcat
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
chentomcat 1.0 8c3fc729e0f1 About a minute ago 684MB
nginx latest 605c77e624dd 4 months ago 141MB
tomcat 9.0 b8e65a4d736d 5 months ago 680MB
tomcat latest fb5657adc892 5 months ago 680MB
centos latest 5d0da3dc9764 8 months ago 231MB
portainer/portainer latest 580c0e4e98b0 14 months ago 79.1MB
为了将容器的数据进行持久化保存的操作。防止删掉容器后,容器内的数据也没有。
作用:挂载宿主机的一个目录
这里把容器想成一个单独的系统,或者说电脑,而你的宿主机目录是一个U盘,挂载后,你往宿主机该目录里放文件,那么通过容器里对应目录便可以访问到此文件,不需要重新生成容器就可以在“容器外部”添加和修改某些文件,如我用Mythri工具检测智能合约漏洞,采用docker容器如下命令:docker run -v $(pwd):/tmp mythril/myth analyze /tmp/test.sol,将宿主机当前目录挂载到容器的tmp目录,则在容器中操作时tmp目录就是当前的目录,在当期目录中新建智能合约或者改变旧的合约如test.sol的内容,再通过analyze命令检测合约即可,既不用重新生成容器,也不需要知道容器的绝对路径从而将新合约复制进去,只需要复制到当前目录即可。
命令:docker run -it -v 主机目录:容器目录 容器名称
# 首先确认下本机linux目录下是没有其他目录的
[root@localhost /]# cd home/
[root@localhost home]#
1、我们首先在本机的home目录下,新建一个名叫ceshi的目录,随后我们将主机的home/ceshi 目录挂载到容器的home目录下。到时候这两个目录任一一个有改动,另外一个目录也能同步改动
# 启动centos容器,并且将主机的home/ceshi目录挂载到容器的home目录,并且成功进入到容器里面
[root@localhost home]# docker run -it -v /home/ceshi:/home centos
[root@9df6ac86d312 /]#
2、进一步查看已经开启数据卷的容器的进程信息,使用inspect命令
[root@localhost ceshi]# docker inspect 9df6ac86d312
3、新开一个会话,进入到linux的home/ceshi目录下,可以看到,ceshi目录是没有任何文件的
[root@localhost home]# cd ceshi/
[root@localhost ceshi]# ls
[root@localhost ceshi]#
4、开始测试,往容器的home目录添加文件,新建test.java文件
[root@9df6ac86d312 /]# cd home/
[root@9df6ac86d312 home]# touch test.java
[root@9df6ac86d312 home]# ls
test.java
[root@9df6ac86d312 home]#
5、去linux的home/ceshi目录查看,是否有新建的test.java文件
[root@localhost ceshi]# ls
test.java
结果:可以看到,主机目录已经成功挂载到容器的目录里。容器里面的home目录有什么变动,linux下的home/ceshi目录也会跟着同步。
下面我们来变动linux中home/ceshi/test.java文件,那容器home目录下的test.java文件会不会也会跟着变动呢?
1、这里,我往linux的test.java文件,输入了一行字,:wq 保存退出。
[root@localhost ceshi]# vi test.java
[root@localhost ceshi]# cat test.java
hello,chenxiansheng
[root@localhost ceshi]#
2、现在去查看容器的test.java文件,可以看到,也是同步成功的
[root@9df6ac86d312 home]# cat test.java
hello,chenxiansheng
[root@9df6ac86d312 home]#
根据上面我们得出结论。容器数据卷功能,是通过在启动容器时,加上-v 参数,写上要挂载的目录和绑定的目录,使得这两个不在同一个层面的目录有了双向绑定的功能,数据可以实现同步(就算是容器已经停止运行,双向绑定的作用依然有效)。
# 下载mysql镜像
[root@localhost ~]# docker pull mysql:5.7
5.7: Pulling from library/mysql
72a69066d2fe: Pull complete
93619dbc5b36: Pull complete
99da31dd6142: Pull complete
626033c43d70: Pull complete
37d5d7efb64e: Pull complete
ac563158d721: Pull complete
d2ba16033dad: Pull complete
0ceb82207cd7: Pull complete
37f2405cae96: Pull complete
e2482e017e53: Pull complete
70deed891d42: Pull complete
Digest: sha256:f2ad209efe9c67104167fc609cca6973c8422939491c9345270175a300419f94
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7
# 查看镜像
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
chentomcat 1.0 8c3fc729e0f1 47 hours ago 684MB
nginx latest 605c77e624dd 4 months ago 141MB
tomcat 9.0 b8e65a4d736d 5 months ago 680MB
tomcat latest fb5657adc892 5 months ago 680MB
mysql 5.7 c20987f18b13 5 months ago 448MB
centos latest 5d0da3dc9764 8 months ago 231MB
portainer/portainer latest 580c0e4e98b0 14 months ago 79.1MB
# 运行mysql容器。
参数说明:
[root@localhost ~]# 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=root --name mysqlO1 mysql:5.7
6a2caa469f09e9ff2417d31634fb50a4624118d1724f236ca0962a62989bb2f8
[root@localhost ~]#
测试连接:
这里我使用Navicat Premium工具连接测试
192.168.239.128 是我的linux地址,可以看到,连接成功
查看linux中的home/mysql文件夹:
然后我们使用Navicat Premium 工具,在该mysql中新建test数据库:
重新查看本机的home/mysql/data目录,可以看到,新增了test文件夹
以上得出结论,我们是在容器的mysql新建了数据库,我们可以在linux上找到容器新建的test数据库,这两个文件夹实现了双向绑定。假如我们把容器删除了,数据也不会丢失,实现了数据的持久化功能。
docker run -d -p --name nginx01 -v /etc/nginx nginx
-P 随机指定端口
[root@localhost /]# docker run -d -P --name nginx02 -v /etc/nginx nginx
5035f960746ba9a373fdeeec59e837f77793465055ade7e46e49d11d3e820a6d
# 使用docker volume 命令查看数据卷具体信息
[root@localhost /]# docker volume --help
Usage: docker volume COMMAND
Manage volumes
Commands:
create Create a volume
inspect Display detailed information on one or more volumes
ls List volumes
prune Remove all unused local volumes
rm Remove one or more volumes
Run 'docker volume COMMAND --help' for more information on a command.
# docker volume ls 命令列出该数据卷文件夹
[root@localhost /]# docker volume ls
DRIVER VOLUME NAME
local 5935c0c061619752d5939c6c0567a588feacb171ec5bbe15be327e1952a32aef
local d8bd26ce1c9d58e224d378446283b9166f53f1f3d9bb2ae3419d0dd67667cb20
因为上面的命令匿名挂载,也就是没有指定主机目录,所以它会自己生成一个目录,这里我都进入看过,它会把5935c0c061619752d5939c6c0567a588feacb171ec5bbe15be327e1952a32aef 目录挂载到容器的/etc/nginx目录中。
下面我们继续使用docker volume 命令,查看数据卷文件夹具体路径:
[root@localhost home]# docker volume inspect 5935c0c061619752d5939c6c0567a588feacb171ec5bbe15be327e1952a32aef
[
{
"CreatedAt": "2022-05-25T21:55:11+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/5935c0c061619752d5939c6c0567a588feacb171ec5bbe15be327e1952a32aef/_data",
"Name": "5935c0c061619752d5939c6c0567a588feacb171ec5bbe15be327e1952a32aef",
"Options": null,
"Scope": "local"
}
]
从上面可以看出来,数据卷的文件夹放在/var/lib/docker/volumes/目录下,我们直接去到该目录下查看是否有nginx的文件
[root@localhost home]# cd /var/lib/docker/volumes/5935c0c061619752d5939c6c0567a588feacb171ec5bbe15be327e1952a32aef/
[root@localhost 5935c0c061619752d5939c6c0567a588feacb171ec5bbe15be327e1952a32aef]# ls
_data
[root@localhost 5935c0c061619752d5939c6c0567a588feacb171ec5bbe15be327e1952a32aef]# cd _data/
[root@localhost _data]# ls
conf.d fastcgi_params mime.types modules nginx.conf scgi_params uwsgi_params
[root@localhost _data]# cat nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
[root@localhost _data]#
可以看到,nginx文件也是正确同步的。匿名挂载的缺点,就是生成的挂载目录的名字是不确定的,使我们不知道真正挂载的目录是哪一个,只能一个个找。
同样,我们启动一个nginx容器,这一次我们指定主机目录juming (没有放在相对路径上,前面不需要加 “/”) ,此时再用docker volume 命令去查看目录的路径
[root@localhost /]# docker run -d -P --name nginx04 -v juming:/etc/nginx nginx
d68b6d085d0304d43e205c5627c1fc790aea3391b09bf7b6304b2c71cafc8376
[root@localhost /]# docker volume ls
DRIVER VOLUME NAME
local 5935c0c061619752d5939c6c0567a588feacb171ec5bbe15be327e1952a32aef
local d8bd26ce1c9d58e224d378446283b9166f53f1f3d9bb2ae3419d0dd67667cb20
local juming
# 使用 docker volume inspect 查看挂载目录的路径
[root@localhost _data]# docker volume inspect juming
[
{
"CreatedAt": "2022-05-25T22:29:57+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/juming/_data",
"Name": "juming",
"Options": null,
"Scope": "local"
}
]
# 进入到该挂载目录的_data目录,可以看到nginx.conf 也是存在的,说明具名挂载也是成功的
[root@localhost /]# cd var/lib/docker/volumes/juming/_data/
[root@localhost _data]# ls
conf.d fastcgi_params mime.types modules nginx.conf scgi_params uwsgi_params
[root@localhost _data]# cat nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
[root@localhost _data]#
从上面的匿名挂载和具名挂载得出结论,
不同点: 匿名挂载就是挂载的时候不主动指定要挂载的主机目录,此时会自动生成一个挂载目录,但是具体叫什么名字我们不清楚,只能使用 ”docker inspect 容器id “命令,从进程信息的mounts找出挂载的本机目录名称。 具名挂载就是在挂载的时候手动指定一个要挂载的目录,此时我们 ”docker volume ls “命令就能很轻松找到对应的主机目录。
相同点:具名挂载和匿名挂载的主机目录都是存放在"/var/lib/docker/volumes/"路径上的
拓展:
# 通过 -v 容器内路径:ro /rw 改变读写权限
ro: # 只读
rw: # 可读可写
docker run -d -P --name nginx03 -v /home/juming:/etc/nginx:ro nginx
docker run -d -P --name nginx03 -v /home/juming:/etc/nginx:rw nginx
#ro 只要看到ro 就说明这个路径只能通过宿主机来操作,容器内部无法操作!(测试:看下面两张图片)
往主机添加test.java文件(图1),可以看到容器也有test.java文件(图2),但是往容器添加test2.java文件,却报只有只读权限(图2)。
图1
Dockerfile 就是用来构建 docker 镜像的构建文件,命令脚本!
通过这个脚本可以生成镜像,镜像是一层一层的,脚本一个个的命令。每一个命令都是一层。
构建自己的镜像
# 创建一个dockerfile文件,名字可以随机,建议叫:dockerfile
# 文件中的内容 指令(大写) 参数
# 第一步,在本机的home目录新建一个docker-test-volume 目录
[root@localhost home]# mkdir docker-test-volume
[root@localhost home]# ls
ceshi chenmaolin chenxiansheng222.java docker-test-volume juming mysql
# 第二部,进入到该目录,新建一个名为dockerfile1的文件,并写上内容
[root@localhost home]# cd docker-test-volume/
[root@localhost docker-test-volume]# vi dockerfile1
[root@localhost docker-test-volume]# cat dockerfile1
FROM centos
VOLUME ["volume01","volume02"]
CMD echo "-------end------"
CMD /bin/bash
# 第三步,使用构建镜像的命,docker build
-f # 指定要构建的文件
-t # 要生成的镜像
. # 表示当前目录
[root@localhost docker-test-volume]# docker build -f /home/docker-test-volume/dockerfile1 -t chenxiansheng/centos:1.0 .
Sending build context to Docker daemon 2.048kB
Step 1/4 : FROM centos
---> 5d0da3dc9764
Step 2/4 : VOLUME ["volume01","volume02"]
---> Running in de2d516d27b4
Removing intermediate container de2d516d27b4
---> ab91177ccd23
Step 3/4 : CMD echo "-------end------"
---> Running in da532b3a90af
Removing intermediate container da532b3a90af
---> 3dfd8b7d5bde
Step 4/4 : CMD /bin/bash
---> Running in df8f5c472181
Removing intermediate container df8f5c472181
---> b0b6b03694f5
Successfully built b0b6b03694f5
Successfully tagged chenxiansheng/centos:1.0
# 第四步,查看镜像,可以看到自己的镜像构建成功,chenxiansheng/centos
[root@localhost docker-test-volume]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
chenxiansheng/centos 1.0 b0b6b03694f5 8 seconds ago 231MB
chentomcat 1.0 8c3fc729e0f1 3 days ago 684MB
nginx latest 605c77e624dd 4 months ago 141MB
tomcat 9.0 b8e65a4d736d 5 months ago 680MB
tomcat latest fb5657adc892 5 months ago 680MB
mysql 5.7 c20987f18b13 5 months ago 448MB
centos latest 5d0da3dc9764 8 months ago 231MB
portainer/portainer latest 580c0e4e98b0 14 months ago 79.1MB
启动自己镜像进行测试
但是上面的挂载有一个问题,那就我们并没有指定本机的目录,只是挂载的容器里的目录 volume01 和volume02 ,这是属于匿名挂载。所以它生成的本机目录是一窜很长的16进制表示的目录名。
使用docker inspect 容器id 命令,查看该容器的进程信息,就可以得到该容器的进程信息,可以从进程信息找到该容器的挂载的本机目录
[root@localhost /]# docker inspect d0ea1e9cf82e
从进程信息中,找到mounts ,可以看到主机的目录
跟前面的数据卷一样,文件也是双向绑定的。在容器里的volume01目录有变动,本机的/var/lib/docker/volumes/656e215f074529196d4b1b8df2e9339286b81bba49beebeb03ea2c483d25e902/_data 也会跟着同步。同理,volume02 也一样。
以上这种构建dockerfile的方式未来我们用的十分多。因为偶们通常会构建自己的镜像!
就是多个容器间进行数据共享,使用–volumes-from 命令
第一步,启动一个docker01容器,就用我们前面自己构建的镜像
[root@localhost docker-test-volume]# docker run -it --name docker01 chenxiansheng/centos:1.0
[root@cf7f334a2601 /]# ls -l
total 0
lrwxrwxrwx. 1 root root 7 Nov 3 2020 bin -> usr/bin
drwxr-xr-x. 5 root root 360 May 26 15:04 dev
drwxr-xr-x. 1 root root 66 May 26 15:04 etc
drwxr-xr-x. 2 root root 6 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 6 Sep 15 2021 lost+found
drwxr-xr-x. 2 root root 6 Nov 3 2020 media
drwxr-xr-x. 2 root root 6 Nov 3 2020 mnt
drwxr-xr-x. 2 root root 6 Nov 3 2020 opt
dr-xr-xr-x. 126 root root 0 May 26 15:04 proc
dr-xr-x---. 2 root root 162 Sep 15 2021 root
drwxr-xr-x. 11 root root 163 Sep 15 2021 run
lrwxrwxrwx. 1 root root 8 Nov 3 2020 sbin -> usr/sbin
drwxr-xr-x. 2 root root 6 Nov 3 2020 srv
dr-xr-xr-x. 13 root root 0 May 26 11:41 sys
drwxrwxrwt. 7 root root 171 Sep 15 2021 tmp
drwxr-xr-x. 12 root root 144 Sep 15 2021 usr
drwxr-xr-x. 20 root root 262 Sep 15 2021 var
drwxr-xr-x. 2 root root 6 May 26 15:04 volume01
drwxr-xr-x. 2 root root 6 May 26 15:04 volume02
# 随后使用ctrl+P+Q ,后台运行并退出
[root@cf7f334a2601 /]# [root@localhost docker-test-volume]#
第二步,继承docker01镜像,启动一个docker02容器,使用–volumes-from 参数
[root@localhost docker-test-volume]# docker run -it --name docker02 --volumes-from docker01 chenxiansheng/centos:1.0
[root@f0cc63e30a17 /]# ls -l
total 0
lrwxrwxrwx. 1 root root 7 Nov 3 2020 bin -> usr/bin
drwxr-xr-x. 5 root root 360 May 26 15:07 dev
drwxr-xr-x. 1 root root 66 May 26 15:07 etc
drwxr-xr-x. 2 root root 6 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 6 Sep 15 2021 lost+found
drwxr-xr-x. 2 root root 6 Nov 3 2020 media
drwxr-xr-x. 2 root root 6 Nov 3 2020 mnt
drwxr-xr-x. 2 root root 6 Nov 3 2020 opt
dr-xr-xr-x. 125 root root 0 May 26 15:07 proc
dr-xr-x---. 2 root root 162 Sep 15 2021 root
drwxr-xr-x. 11 root root 163 Sep 15 2021 run
lrwxrwxrwx. 1 root root 8 Nov 3 2020 sbin -> usr/sbin
drwxr-xr-x. 2 root root 6 Nov 3 2020 srv
dr-xr-xr-x. 13 root root 0 May 26 11:41 sys
drwxrwxrwt. 7 root root 171 Sep 15 2021 tmp
drwxr-xr-x. 12 root root 144 Sep 15 2021 usr
drwxr-xr-x. 20 root root 262 Sep 15 2021 var
drwxr-xr-x. 2 root root 6 May 26 15:04 volume01
drwxr-xr-x. 2 root root 6 May 26 15:04 volume02
可以看到,docker01 和docker02 都拥有volume01 和volume02 目录, 这个两个目录是同步数据的,下面我们来测试一下:
# 我们在docker01 容器的volume01 目录新建一个 test.java
[root@cf7f334a2601 /]# cd volume01/
[root@cf7f334a2601 volume01]# ls
[root@cf7f334a2601 volume01]# touch test.java
[root@cf7f334a2601 volume01]# ls
test.java
[root@cf7f334a2601 volume01]#
此时去到docker02 容器,查看volume01 文件,test.java文化也是存在的,这就实现了数据卷容器的同步功能
[root@f0cc63e30a17 /]# cd volume01
[root@f0cc63e30a17 volume01]# ls
test.java
[root@f0cc63e30a17 volume01]#
那么,如果我要同步容器3、容器4 呢,这里继续测试,我们继承docker02 ,启动docker03
[root@localhost ~]# docker run -it --name docker03 --volumes-from docker02 chenxiansheng/centos:1.0
[root@97396699c735 /]# ls -l
total 0
lrwxrwxrwx. 1 root root 7 Nov 3 2020 bin -> usr/bin
drwxr-xr-x. 5 root root 360 May 26 15:18 dev
drwxr-xr-x. 1 root root 66 May 26 15:17 etc
drwxr-xr-x. 2 root root 6 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 6 Sep 15 2021 lost+found
drwxr-xr-x. 2 root root 6 Nov 3 2020 media
drwxr-xr-x. 2 root root 6 Nov 3 2020 mnt
drwxr-xr-x. 2 root root 6 Nov 3 2020 opt
dr-xr-xr-x. 130 root root 0 May 26 15:17 proc
dr-xr-x---. 2 root root 162 Sep 15 2021 root
drwxr-xr-x. 11 root root 163 Sep 15 2021 run
lrwxrwxrwx. 1 root root 8 Nov 3 2020 sbin -> usr/sbin
drwxr-xr-x. 2 root root 6 Nov 3 2020 srv
dr-xr-xr-x. 13 root root 0 May 26 11:41 sys
drwxrwxrwt. 7 root root 171 Sep 15 2021 tmp
drwxr-xr-x. 12 root root 144 Sep 15 2021 usr
drwxr-xr-x. 20 root root 262 Sep 15 2021 var
drwxr-xr-x. 2 root root 23 May 26 15:11 volume01
drwxr-xr-x. 2 root root 6 May 26 15:04 volume02
[root@97396699c735 /]# cd volume01
[root@97396699c735 volume01]# ls
test.java
[root@97396699c735 volume01]#
可以看到,同步依然是有效的。
如果docker03 继承docker01 启动,可不可以呢? 答案也是肯定的,也是能实现数据共享的!!
删除了docker 01 后,docker02 和docker03 依然可以实现数据共享。跟容器是否启动是无关的!
所以得出结论,要实现容器间的数据共享,只需要在docker run 增加–volumes-from 参数 父类容器名称 ,就可以实现容器间的数据共享。 只要有共同一个父类就可以。
结论:容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止
但是一旦持久化到了本地,这个时候,本地的数据就不会删除,就算容器没有再使用了。
构建步骤:
很多官方的镜像都是基础包,很多功能没有,我们通常会自己搭建自己的镜像。
CMD # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD # 当构建一个被继承DockerFile 这个时候就会运行ONBUILD 的指令,触发指令
COPY # 类似ADD,将我们文件拷贝到镜像中
ENY # 构建的时候设置环境变量!
Docker Hub 中99% 镜像都是从这个基础镜像过来的FROM scratch ,然后配置需要的软件和配置要进行的构建
我们先启动centos ,在容器里面使用 vim 命令和 ifconfig 命令,发现,都是不支持这个命令的,说明官方的centos容器是阉割版的,那我们就自己构建一个centos,是它能够支持vim 和ifconfig命令
创建目录,并在该目录新建一个mydockerfilecentos 文件,并且写上要构建的镜像指令
[root@localhost home]# mkdir firstdockerfile
[root@localhost home]# ls
ceshi chenmaolin chenxiansheng222.java docker-test-volume firstdockerfile juming mysql
[root@localhost home]# cd firstdockerfile/
# 1 编写Dockerfile 文件
[root@localhost firstdockerfile]# vi mydockerfilecentos
[root@localhost firstdockerfile]# cat mydockerfilecentos
FROM centos:7 # 指定了centos 为基础镜像,因为本机的centos版本就是7.9,所以这里也要下7,都则会下载不了
MAINTAINER chenxiansheng<1050480930@qq.com> # 维护者西你想
ENV MYPATH /usr/local # 设置环境变量
WORKDIR $MYPATH # 设置当前工作目录
RUN yum -y install vim # 默认下载vim指令
RUN yum -y insatll net-tools # 默认下载网络工具包
EXPOSE 80 # 指定对外的端口
CMD echo $MYPATH # 容器启动时,要运行的命令,将工作目录打印出来
CMD echo "----end------" # 容器启动时,要运行的命令
CMD /bin/bash # 容器启动时,要启动的命令行
# 2、通过这个文件构建镜像
# 命令 docker build -f dockerfile文件路径
[root@localhost firstdockerfile]# docker build -f mydockerfilecentos -t mycentos:0.1 .
注意查看docker容器里面的centos版本是不是8.0,本机的centos是7.9的情况,这种时候构建遇到 yum命令时会报错,需要在dockerfile文件中,指定下载为7版本的centos,即可解决
# 3、 测试运行
[root@localhost firstdockerfile]# docker run -it mycentos:0.1
# 这里可以看到,容器默认就是进入到/usr/local,这就是我们前面设置的工作目录
[root@547054def8e6 local]# pwd
/usr/local
# 可以看到我们构建的镜像,可以使用ifconifg、vim命令了
[root@547054def8e6 local]# ifconfig
eth0: flags=4163,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.4 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:ac:11:00:04 txqueuelen 0 (Ethernet)
RX packets 8 bytes 656 (656.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@547054def8e6 local]#vim
[root@547054def8e6 local]#
我们平时拿到一个镜像,可以研究一下它是怎么做的
[root@localhost firstdockerfile]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mycentos 0.1 c80a46b4bab7 12 minutes ago 601MB
# 使用镜像id查看变更历史(也就是可以查看这些镜像的dockerfile是怎么写的)
[root@localhost firstdockerfile]# docker history c80a46b4bab7
IMAGE CREATED CREATED BY SIZE COMMENT
c80a46b4bab7 13 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "/bin… 0B
522954b80b85 13 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
dfcfc1df60c5 13 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
a04211a9bee4 13 minutes ago /bin/sh -c #(nop) EXPOSE 80 0B
536afb4c9003 13 minutes ago /bin/sh -c yum -y install net-tools 171MB
497262217236 13 minutes ago /bin/sh -c yum -y install vim 226MB
f4d69a0c750d 20 minutes ago /bin/sh -c #(nop) WORKDIR /usr/local 0B
098b9103d5fb 20 minutes ago /bin/sh -c #(nop) ENV MYPATH=/usr/local 0B
722b4df5b913 20 minutes ago /bin/sh -c #(nop) MAINTAINER chenxiansheng<… 0B
eeb6ee3f44bd 8 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
8 months ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B
8 months ago /bin/sh -c #(nop) ADD file:b3ebbe8bd304723d4… 204MB
[root@localhost firstdockerfile]#
CMD 和 ENTRYPOINT 区别
CMD # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令
测试cmd
# 构建dockerfile镜像
[root@localhost firstdockerfile]# vi dockerfile-cmd-test
# 这里的镜像就只运行 ls -a 命令
[root@localhost firstdockerfile]# cat dockerfile-cmd-test
FROM centos
CMD ["ls","-a"]
# 构建cmd镜像
[root@localhost firstdockerfile]# docker build -f dockerfile-cmd-test -t cmdtest .
Sending build context to Docker daemon 3.072kB
Step 1/2 : FROM centos
---> 5d0da3dc9764
Step 2/2 : CMD ["ls","-a"]
---> Running in 82f7e399a1f0
Removing intermediate container 82f7e399a1f0
---> 0b2e5b872f1c
Successfully built 0b2e5b872f1c
Successfully tagged cmdtest:latest
# 运行cmd镜像
[root@localhost firstdockerfile]# docker run 0b2e5b872f1c
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
# 上面可以看到,正确执行了 ls -a 命令,下面我们想要追加一个命令,变成 ls -l
[root@localhost firstdockerfile]# docker run 0b2e5b872f1c -l
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "-l": executable file not found in $PATH: unknown.
# cmd 的清理下,会用-l 替换 ["ls","-a"] 命令, 因为-l 不是命令,所以报错了
测试ENTRYPOINT
# 构建dockerfile镜像
[root@localhost firstdockerfile]# vi docker-entrypoint-test
# 这里和上面一样,该镜像只执行ls -a 命令
[root@localhost firstdockerfile]# cat docker-entrypoint-test
FROM centos
ENTRYPOINT ["ls","-a"]
# 构建entrypoint 镜像
[root@localhost firstdockerfile]# docker build -f docker-entrypoint-test -t entrypointtest .
Sending build context to Docker daemon 4.096kB
Step 1/2 : FROM centos
---> 5d0da3dc9764
Step 2/2 : ENTRYPOINT ["ls","-a"]
---> Running in 221b27881ee1
Removing intermediate container 221b27881ee1
---> 3cdb2e38bcd8
Successfully built 3cdb2e38bcd8
Successfully tagged entrypointtest:latest
# 运行entrypoint 镜像,可以发现,运行成功
[root@localhost firstdockerfile]# docker run 3cdb2e38bcd8
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
# 继续追加命令,直接在后面加 -l
[root@localhost firstdockerfile]# docker run 3cdb2e38bcd8 -l
total 0
drwxr-xr-x. 1 root root 6 May 30 14:45 .
drwxr-xr-x. 1 root root 6 May 30 14:45 ..
-rwxr-xr-x. 1 root root 0 May 30 14:45 .dockerenv
lrwxrwxrwx. 1 root root 7 Nov 3 2020 bin -> usr/bin
drwxr-xr-x. 5 root root 340 May 30 14:45 dev
drwxr-xr-x. 1 root root 66 May 30 14:45 etc
drwxr-xr-x. 2 root root 6 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 6 Sep 15 2021 lost+found
drwxr-xr-x. 2 root root 6 Nov 3 2020 media
drwxr-xr-x. 2 root root 6 Nov 3 2020 mnt
drwxr-xr-x. 2 root root 6 Nov 3 2020 opt
dr-xr-xr-x. 135 root root 0 May 30 14:45 proc
dr-xr-x---. 2 root root 162 Sep 15 2021 root
drwxr-xr-x. 11 root root 163 Sep 15 2021 run
lrwxrwxrwx. 1 root root 8 Nov 3 2020 sbin -> usr/sbin
drwxr-xr-x. 2 root root 6 Nov 3 2020 srv
dr-xr-xr-x. 13 root root 0 May 30 11:07 sys
drwxrwxrwt. 7 root root 171 Sep 15 2021 tmp
drwxr-xr-x. 12 root root 144 Sep 15 2021 usr
drwxr-xr-x. 20 root root 262 Sep 15 2021 var
# 结果:-l 命令执行成功了,是因为 他只是替换了-a ,变成了 ls -l 了。所以成功运行
1、准备镜像文件,tomcat压缩包,jdk压缩包
2、新建readme.txt,Dockerfile文件 ,并且填写dockerfile指令(这里我们是要建一个tomcat 和jdk的镜像),随后构建写好的dockerfile文件
[root@localhost tomcat]# touch readme.txt
[root@localhost tomcat]# vi Dockerfile
# 填写dockerfile指令,这里我们是要建一个tomcat 和jdk的镜像
[root@localhost tomcat]# cat Dockerfile
FROM centos:7
MAINTAINER chenxiansheng<1050480930@qq.com>
COPY readme.txt /usr/local/readme.txt
ADD jdk-8u60-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.63.tar.gz /usr/local/
RUN yum -y install vim
ENV MYPATH /usr/local
WORKDIR $MYPATH
ENV JAVA_HOME /usr/local/jdk1.8.0_60
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.63
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.63
ENV PATH $PATH:$JAVA_HOME/bin:$CATAINA_HOME/lib:$CATALINA_HOME/bin
EXPOSE 8080
CMD /usr/local/apache-tomcat-9.0.63/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.63/bin/logs/catalina.out
# 开始构建dockerfile(这里的“.” 代表构建当前目录下的Dockfile文件)
[root@localhost tomcat]# docker build -t diytomcat .
Sending build context to Docker daemon 192.8MB
Step 1/15 : FROM centos:7
---> eeb6ee3f44bd
Step 2/15 : MAINTAINER chenxiansheng<1050480930@qq.com>
---> Using cache
---> 722b4df5b913
#....... 省略构建日志
Successfully built 7c5296e1e145
Successfully tagged diytomcat:latest
# 查看镜像,可以发现,我们的diytomcat 构建成功
[root@localhost tomcat]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
diytomcat latest 7c5296e1e145 2 minutes ago 811MB
第3步、启动该镜像
[root@localhost tomcat]# docker run -d -p 9090:8080 --name chenxianshengtomcat -v /home/tomcat/test:/usr/local/apache-tomcat-9.0.63/webapps/test -v /home/tomcat/tomcatlogs/:/usr/local/apache-tomcat-9.0.63/logs diytomcat
49b22d1db8763cee40876a75a4ed11cebdc51462153f981253d1a04582cca618
第4步,开始测试,tomcat是否成功
直接去访问linux地址的9090端口,查看是否有tomcat 页面:
可以看到,tomcat是正常运行的
第五步。继续测试tomcat ,因为我们在启动自己制作的diytomcat镜像时,将本机的/home/tomcat/test 目录与容器里面的/usr/local/apache-tomcat-9.0.63/webapps/test 绑定了,所以,我们直接往本机的/home/tomcat/test 目录,新增index.jsp ,那么容器的apache-tomcat-9.0.63/webapps/test 目录也是会有index.jsp文件的,这时候去访问本机地址:9090/test 地址,是会识别到index.jsp文件的,并把里面的内容解析成网页的。
1)进入到本机的/home/tomcat/test目录,新建index.jsp ,并且填上内容:
[root@localhost tomcat]# cd test/
[root@localhost test]# vi index.jsp
[root@localhost test]# cat index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
"utf-8">
chenxiansheng(runoob.com)</title>
</head>
Hello World,chenxiansheng!
<%
out.println("--------my test web logs-------");
%>
</body>
</html>
# 查看该容器是否也同步了index.jsp文件,可以看到同步成功
[root@localhost tomcat]# docker exec -it 49b22d1db8763 /bin/bash
[root@49b22d1db876 local]# cd /usr/local/apache-tomcat-9.0.63/webapps/test/
[root@49b22d1db876 test]# ls
index.jsp
2) 直接访问本地地址:9090/test 路径
可以看到,容器里面的tomcat正确的解析了index.jsp文件,生成了网页。并且我们可以去本机查看容器里面的logs日志(这个也是在启动该镜像的时候绑定好的)
结论1:该diytomcat镜像,是我们自己一手打造出来的,实现了tomcat镜像该有的功能。
结论2:通过这种双向绑定的方式,我们的linux本机不需要安装tomcat镜像,只需要将其中的一个目录绑定在有tomcat的docker容器里,我们就可以实现,在本机上传web工程,让docker容器解析的功能。
1、地址 https://hub.docker.com/ 注册自己账号
2、确定这个账号可以登录
3、在我们的服务器上提交自己的镜像
# 使用docker login 命令
[root@localhost tomcatlogs]# docker login -u morningchan
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@localhost tomcatlogs]#
登录成功后,需要修改tag ,也就是给自己的镜像一个版本号,使用docker tag 命令
[root@localhost tomcatlogs]# docker tag 7c5296e1e145 morningchan/diytomcat:1.0
推送自己的镜像到docker hub ,使用docker push 命令
[root@localhost tomcatlogs]# docker push morning/diytomcat:1.0
注意:修改tag的时候,最好修改成自己dockerhub 用户名字/ 镜像名称的形式, 如果前面用户自己的docker hub镜像命名,那后面push就会被拒绝。 这里我的docker hub 用户名就叫morningchan ,