Docker学习
Docker概述
一、Docker为什么会出现?
一款产品:开发--上线 两套环境!应用环境,应用配置! 开发 ...... 运维。问题:我在我的电脑上可以运行! 版本更新,导致服务不可用!对于运维来说,考验九十分大?
环境配置是十分的麻烦,每一个机器都要部署环境(集群Redis、ES、Hadoop...)!费时费力
发布一个项目(jar+(Redis MySql jdk ES)项目能不能都带上环境打包!
之前在服务器配置一个应用的环境Redis MySql jdk ES Hadoop ,配置超麻烦,不能够跨平台。
Windows, 最后发布到Linux!
传统:开发jar,环境运维来做!
现在:开发打包部署上线,一套流程做完!
java --- apk --- 发布 (应用商店)--- 张三使用apk --- 安装即可用!
java --- jar (环境) --- 打包项目带上环境(镜像)--- (Docker仓库:商店)--- 下载我们发布的镜像---直接运行即可!
Docker 给以上的问题,提出了解决方案!

Docker的思想就来自于集装箱!
JRE --- 多个应用(端口冲突) --- 原来都是交叉的!
隔离: Docker核心思想!打包装箱!每个箱子都是相互隔离的。
Docker 通过隔离机制,可以将服务器利用到极致!
本质: 所有的技术都是因为出现了一些问题,我们需要去解决,才去学习!
二、Docker的历史
2010年,几个搞IT的年轻人,就在美国成立了一家公司 dotCloud
做一些pass的云计算服务! LXC 有关的容器技术!
他们将自己的技术(容器化技术)命名 就是Docker!
Docker刚刚诞生的时候,没有引起行业的注意!dotCloud,就活不下去!
开源
开发源代码!
2013年,Docker开源!
Docker越来越多的人发现docker的优点! 火了,Docker每个月都会更新一个版本!
2014年4月9日,Docker1.0发布!
Docker为什么这么火? 十分的轻巧!
在容器技术出来之前,我们都是使用虚拟机技术!
虚拟机:在window中装一个Vmware,通过这个软件我们可以虚拟出来一台或者多台电脑! 笨重!
虚拟机也是属于虚拟化技术,Docker容器技术,也是一种虚拟化技术!
vm: linux centos原生镜像(一台电脑!) 需要开启多个虚拟机! 几个G 几分钟
docker: 隔离,镜像(最核心的环境 4m + jdk + mysql)十分的小巧,运行镜像就可以了! 小巧
到现在,所有开发人员都必须要会用Docker!
聊聊Docker
Docker 是基于Go语言开发的!开源项目!

三、Docker 能干嘛
之前的虚拟机技术!
虚拟技术缺点:
-
资源占用十分多
-
冗余步骤多
-
启动很慢
容器化技术
容器化技术不是模拟的一个完整的操作系统
比较Docker 和 虚拟机技术的不同
- 传统虚拟机,虚拟出一个硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件
- 容器内的应用直接运行在 宿主机 上,容器是没有自己的内核的,也没有虚拟我们的硬件,所以就轻便了
- 每个容器间都是相互隔离,每个容器内都有一个属于自己的文件系统,互不影响
DevOps (开发,运维)
应用更快速的交付和部署
传统:一堆帮助文档、安装程序
Docker:打包镜像、发布测试、一键运行
更便捷的升级和扩容
使用了Docker之后,我们部署应用就和搭积木一样!
项目打包为一个镜像,扩展,服务器A!服务器B
更简单的系统运维
在容器化之后,我们的开发,测试环境都是高度一致的。
更高效的计算资源利用
Docker 是 内核级别的 虚拟化,可以在一个物理机上可以运行很多的容器实例!服务器的性能 可以被压榨到极致
四、Docker 安装
1、Docker的基本组成

镜像(image):
docker镜像就好比是一个模板,可以通过这个模板来创建容器服务,tomcat镜像》run》tomcat01 容器(提供服务),通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中的)。
容器(container):
Docker利用容器技术,独立运行一个或者一个组应用,通过镜像来创建的。
启动,停止,删除,基本命令!
目前就可以把这个容器理解为就是一个简易的linux系统
仓库(repository):
仓库就是存放镜像的地方!
仓库分为公有仓库和私有仓库!
Docker Hub (默认是国外的)
阿里云...都有容器服务器(配置镜像加速)
2、Windows Docker 安装
参考链接:https://www.runoob.com/docker/windows-docker-install.html
3、Centos 安装
# 1、手动卸载旧版本
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
# 2、使用 Docker 仓库进行安装 如果找不到命令就执行: yum -y install yum-utils
yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 3、更新
yum makecache fast
# 4、安装 Docker Engine-Community
yum install docker-ce docker-ce-cli containerd.io
# 5、启动docker
systemctl start docker
# 6、查看docker 版本
docker version
# 7、helloworld 测试
docker run hello-world
# 没有yum命令话,先yum -y update
# 添加镜像仓库 加速下载
# 1、编辑 /etc/docker/daemon.json 如果不存在就新建(注意文件名不能乱起)
{
"registry-mirrors":[
"https://reg-mirror.qiniu.com",
"https://hub-mirror.c.163.com",
"https://docker.mirrors.ustc.edu.cn"
]
}
# 2、重启动docker服务
systemctl daemon-reload
systemctl restart docker
# 3、查看加速器是否生效
docker info
# 原文链接 https://blog.csdn.net/sayyy/article/details/114993470
4、HelloWorld 流程

5、底层原理
Docker是怎么工作的?
Docker是一个Clint-Server 结构的系统,Docker的守护进程运行在主机上,通过Socket从客户端访问!
DockertServer接收到Docker-Client 的指令,就会执行这个命令!
Docker为什么比VM快
- Docker有着比虚拟机更少的抽象层
- docker利用的是宿主机的内核,vm需要的是Guest OS
所以所,新建一个容器的时候,docker不需要像虚拟机一样重新加载一个操作系统内核。虚拟机是加载GuestOS 分钟级别的,而docker是利用宿主机的操作系统,省略了这个复杂的过程,秒级!
五、Docker的常用命令
1、帮助命令
docker version # 显示docker的版本信息
docker info # 显示docker的系统信息,包括镜像和容器的数量
docker 命令 --help # 帮助命令
2、镜像命令
docker images 查看所有本地的主机上的镜像
PS C:\Users\Administrator># docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest d1165f221234 2 days ago 13.3kB
# 解释
REPOSITORY 镜像的仓库源
TAG 镜像的标签
IMAGE ID 镜像的id
CREATED 镜像的创建时间
SIZE 镜像的大小
# 可选项
-a, --all # 列出所有镜像
-q, --quiet # 只显示镜像的id
docker search 搜索镜像
PS C:\Users\Administrator># docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 10585 [OK]
mariadb MariaDB Server is a high performing open sou… 3960 [OK]
# 可选项,通过搜藏来过滤
--filter=STARS=3000 # 搜索出来的镜像就是STARS 大于3000的
PS C:\Users\Administrator># docker search mysql --filter=STARS=3000
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 10585 [OK]
mariadb MariaDB Server is a high performing open sou… 3960 [OK]
docker pull 下载镜像
# 下载镜像 docker pull 镜像名[:tag]
PS C:\Users\Administrator># docker pull mysql
Using default tag: latest
latest: Pulling from library/mysql
45b42c59be33: Downloading 277.5kB/27.1MB
b4f790bd91da: Download complete
325ae51788e9: Downloading 539.7kB
adcb9439d751: Downloading 523.3kB/1.419MB
docker rmi 删除镜像!
PS C:\Users\Administrator># docker rmi -f 容器id # 删除指定的镜像
PS C:\Users\Administrator># docker rmi -f 容器id 容器id 容器id # 删除多个镜像
PS C:\Users\Administrator># docker rmi -f ${docker images -aq} # 删除全部的镜像
3、容器命令
说明:我们有了镜像才可以创建容器,lilnux,下载一个centos镜像来测试学习
docker pull centos
新建容器并启动
docker run [可选参数] image
# 参数说明
-- name="Name" 容器名字 tomcat01 tomcat02 用来区分容器
-d 后台方式运行
-it 使用交互方式运行,进入容器查看内容
-p 指定容器的端口 -p 8080:8080
-p ip:主机端口:容器端口
-p 主机端口:容器端口
-p 容器端口
-P 随机指定端口
# 测试,启动并进入容器
PS C:\Users\Administrator># docker run -it centos /bin/bash
[root@7520561c9ba4 /]# ls # 查看容器内的centos 基础版本,很多功能是不完善的
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
# 从容器中退回主机
[root@7520561c9ba4 /]# exit
exit
PS C:\Users\Administrator>
列出所有的运行的容器
# docker ps 命令
# 列出当前正在运行的容器
-a # 列出当前正在运行的容器+带出历史运行过的容器
-n=? #显示最近创建的容器
-q # 只显示容器的编号
PS C:\Users\Administrator># docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
PS C:\Users\Administrator> docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS
7520561c9ba4 centos "/bin/bash" 5 minutes ago Exited (127) 4
f1de6ee57579 centos "/bin/bash" 15 hours ago Exited (0) 15
退出容器
exit # 直接容器停止并退出
ctrl + P + Q # 容器不停止退出
删除容器
docker rm 容器id # 删除指定的容器,不能删除正在运行的容器,如果要强制删除 rm -f
docker rm -f $(docker ps -aq) # 删除所有的容器
启动和停止容器的操作
docker start 容器id # 启动容器
docker restart 容器id # 重启容器
docker stop 容器id # 停止当前正在运行的容器
docker kill 容器id # 强制停止当前容器
4、常用其他命令
后台启动容器
# 命令 docker run -d 镜像名!
PS C:\Users\Administrator># docker run -d centos
# 问题docker ps,发现 centos 停止了
#常见的坑,docker 容器后台启动运行,就必须要有一个前台进程,docke发现没有应用,就会自动停止
#nginx, 容器启动后,发现自己没有提供服务,就会立刻停止,就是没有程序了
查看日志
docker logs -f -t -tail 容器,没有日志
# 自己编写一段shell脚本
PS C:\Users\Administrator># docker run -d centos /bin/sh -c "while true;do echo lk;sleep 1;done"
#[root@7520561c9ba4 /]# docker ps
CONTAINER ID IMAGE
dce7b86171bf centos
# 显示日志
-tf # 显示日志
--tail number # 要显示日志条数
[root@7520561c9ba4 /]# docker logs -tf --tail 10 dce7b86171bf
查看容器中进程信息 ps
# 命令 docker top 容器id
PS C:\Users\Administrator> docker top 749eb7f618ac
UID PID PPID C STIME TTY TIME CMD
root 3247 3221 0 00:44 ? 00:00:00 /bin/bash
查看镜像中的元数据
# 命令
docker inspect 容器id
# 测试
PS C:\Users\Administrator># docker inspect 749eb7f618ac
[
{
"Id": "749eb7f618ac373f85146d5098ff28726f548e52f8497b163dd763ac88bc0296",
"Created": "2021-03-09T00:44:58.1283953Z",
"Path": "/bin/bash",
"Args": [],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 3247,
"ExitCode": 0,
"Error": "",
"StartedAt": "2021-03-09T00:44:58.5271509Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:300e315adb2f96afe5f0b2780b87f28ae95231fe3bdd1e16b9ba606307728f55",
"ResolvConfPath": "/var/lib/docker/containers/749eb7f618ac373f85146d5098ff28726f548e52f8497b163dd763ac88bc0296/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/749eb7f618ac373f85146d5098ff28726f548e52f8497b163dd763ac88bc0296/hostname",
"HostsPath": "/var/lib/docker/containers/749eb7f618ac373f85146d5098ff28726f548e52f8497b163dd763ac88bc0296/hosts",
"LogPath": "/var/lib/docker/containers/749eb7f618ac373f85146d5098ff28726f548e52f8497b163dd763ac88bc0296/749eb7f618ac373f85146d5098ff28726f548e52f8497b163dd763ac88bc0296-json.log",
"Name": "/xenodochial_yonath",
"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": [
26,
135
],
"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/f0c86049fdcd855f9fc494ed19ec5b8eca15c495982924facfd35e91aba10715-init/diff:/var/lib/docker/overlay2/d30dfcf1eb559b0743c93eb99db934ffabfd699294acf97233fb89d75f81153d/diff",
"MergedDir": "/var/lib/docker/overlay2/f0c86049fdcd855f9fc494ed19ec5b8eca15c495982924facfd35e91aba10715/merged",
"UpperDir": "/var/lib/docker/overlay2/f0c86049fdcd855f9fc494ed19ec5b8eca15c495982924facfd35e91aba10715/diff",
"WorkDir": "/var/lib/docker/overlay2/f0c86049fdcd855f9fc494ed19ec5b8eca15c495982924facfd35e91aba10715/work"
},
"Name": "overlay2"
},
"Mounts": [],
"Config": {
"Hostname": "749eb7f618ac",
"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": "9ccee0f3fbd852e008a3f5459379770cd57664942c89813a468973761e7e1bb1",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {},
"SandboxKey": "/var/run/docker/netns/9ccee0f3fbd8",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "ff6b18edb335e29b75aad3fb9e0e60a45f2d6323eced0837e25785d13e8ecd25",
"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": "613b251567a8d93644ecc15780177045a033db0540322ff61140e0ba93c11e9b",
"EndpointID": "ff6b18edb335e29b75aad3fb9e0e60a45f2d6323eced0837e25785d13e8ecd25",
"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
# 测试
PS C:\Users\Administrator># docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
749eb7f618ac centos "/bin/bash" 6 minutes ago Up 6 minutes xenodochial_yonath
PS C:\Users\Administrator># docker exec -it 749eb7f618ac /bin/bash
[root@749eb7f618ac /]# ls
bin etc lib lost+found mnt proc run srv tmp var
dev home lib64 media opt root sbin sys usr
[root@749eb7f618ac /]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 00:44 pts/0 00:00:00 /bin/bash
root 15 0 0 00:51 pts/1 00:00:00 /bin/bash
root 30 15 0 00:51 pts/1 00:00:00 ps -ef
# 方式二
docker attach 容器id
# 测试
PS C:\Users\Administrator> docker attach 749eb7f618ac
[root@749eb7f618ac /] / 正在执行当前的代码
# docker exec # 进入容器后开启一个新的终端,可以在里面操作(常用)
# docker attach # 进入容器正在执行的终端,不会启动新的进程!
从容器内拷贝文件到主机上
docker cp 容器id:容器内路径 目的的主机路径
PS C:\Users\Administrator># docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
749eb7f618ac centos "/bin/bash" 9 minutes ago Up 9 minutes xenodochial_yonath
# 进入docker容器内部
PS C:\Users\Administrator># docker attach 749eb7f618ac
[root@749eb7f618ac /]# ls
bin etc lib lost+found mnt proc run srv tmp var
dev home lib64 media opt root sbin sys usr
# 在容器内新建一个文件
[root@749eb7f618ac /]# touch test.java
[root@749eb7f618ac /]# exit
exit
PS C:\Users\Administrator> docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
PS C:\Users\Administrator> docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
749eb7f618ac centos "/bin/bash" 14 minutes ago Exited (0) 17 seconds ago xenodochial_yonath
# 复制文件到主机目录下
PS C:\Users\Administrator># docker cp 749eb7f618ac:/test.java D:/test
# 查看文件
PS C:\Users\Administrator># cd D:/test
PS D:\test># ls
目录: D:\test
Mode LastWriteTime Length Name
-a---- 2021/3/9 8:58 0 test.java
# 拷贝是一个手动过程,未来我们使用 -v 卷的技术,可以实现,自动同步
5、小结

6、作业练习
Docker 安装 Nginx
# 1. 搜索镜像 search
# 2. 下载镜像 pull
# 3. 运行测试
PS D:\test># docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 35c43ace9216 2 weeks ago 133MB
centos latest 300e315adb2f 3 months ago 209MB
# -d 后台运行
# --name 给容器命名
# -p
PS D:\test># docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 35c43ace9216 2 weeks ago 133MB
centos latest 300e315adb2f 3 months ago 209MB
PS D:\test># docker run -d --name nginx01 -p 3344:80 nginx
0bcc4bc0e1b79dbea3331c8bd9c4d96cd79d948257bb16533de99b94cab9ad5f
PS D:\test># docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0bcc4bc0e1b7 nginx "/docker-entrypoint.…" 15 seconds ago Up 13 seconds 0.0.0.0:3344->80/tcp nginx01
# 进入容器
PS D:\test># docker exec -it nginx01 /bin/bash
root@0bcc4bc0e1b7:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
root@0bcc4bc0e1b7:/# cd /etc/nginx
root@0bcc4bc0e1b7:/etc/nginx# ls
conf.d koi-utf mime.types nginx.conf uwsgi_params
fastcgi_params koi-win modules scgi_params win-utf
root@0bcc4bc0e1b7:/etc/nginx#

思考问题:我们每次改动nginx配置文件,都需要进入容器内部?十分的麻烦,我要是可以在容器外部提供一个映射路径,达到在容器外修改文件,容器内部就可以自动修改? -v 数据卷
docker 安装tomcat
# 官方的使用
docker run -it --rm tomcat:9.0
# 我们之前的启动都是后台,停止了容器之后,容器还是可以查到 docker run -it --rm 一般用来测试,用完就删除
# 下载再启动
docker pull tomcat
# 启动运行
docker run -d -p 3355:8080 --name tomcat01 tomcat
# 测试没有问题
#进入容器
#发现问题, 1、linux命令少了 2、没有webapps
思考问题:我们以后要部署项目,如果每次都要进入容器是不是十分麻烦?我要是可以在容器外部提供一个映射路径,我们再外部防止项目,就自动同步到内部就好了
六、Docker 镜像讲解
1、镜像是什么
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和开发环境的软件,它包含运行某个软件的所有内容,包括代码、运行库、环境变量和配置文件
2、Docker 镜像加载原理
UnionFS(联合文件系统)
UnionFS(联合文件系统):UnionFS是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。Union文件系统是Docker镜像的基础,镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特性:一次同时加载多个文件系统,但从外边看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录
Docker镜像加载原理
docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS
bootfs(boot file system)主要包含boot loader 主要是引导加载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
3、分层理解
4、Commit镜像
PS C:\Users\Administrator># docker commit -a="lk" -m="add webapps app" a1170d0a51f2 tomcat02:1.0
sha256:dc32a030c8c7d798b497320fdc24c0308b98aa6712baf691dcd714c66e1b1ca2
PS C:\Users\Administrator># docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat02 1.0 dc32a030c8c7 4 seconds ago 672MB
nginx latest 35c43ace9216 2 weeks ago 133MB
tomcat 9.0 bf4709e77b18 3 weeks ago 667MB
tomcat latest bf4709e77b18 3 weeks ago 667MB
centos latest 300e315adb2f 3 months ago 209MB
七、容器数据卷
1、什么是容器数据卷
docker的理念回顾
将应用和环境打包成一个镜像!
数据?如果数据都在容器中,那么我们删除容器,数据就会丢失!需求:数据可以持久化
MySQL,容器删了,删库跑路!需求:MySQL数据可以存储在本地!
容器之间可以有一个数据共享的技术!Docker哦让其中产生的数据,同步到本地!
这就是卷技术!目录的挂载,将我们容器内的目录,挂载到LInux上面

总结一句话:容器的持久化和同步操作!容器间也是可以数据共享的!
2、使用数据卷
方式一: 直接使用命令来挂载 -v
docker run -it -v 主机目录:容器目录
# 测试
PS D:\> docker run -it -v D:/test/:/home centos /bin/bash
# 启动起来时候我们可以通过 docker inspect 容器id

[root@e4e61d85a410 home]# touch test.java
[root@e4e61d85a410 home]# ls
test.java

手动在D:/test/ 新建test.txt
[root@e4e61d85a410 home]# ls
test.TXT test.java

说明这个绑定是双向绑定
手动删除容器后,本地的数据还在!
3、实战:安装mysql
思考:mysql 的数据持久化的问题!
# 获取镜像
PS D:\> docker pull mysql:8.0.23
# 运行容器,需要数据挂载! 安装启动myql 需要配置密码的
# 官方测试: docker run --name lk-mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:8.0.23
# 启动我们的
-d 后台运行
-p 端口映射
-v 数据卷
-e 环境配置
--name 容器名字
PS D:\># docker run -d -p 3310:3306 -v D:/test/mysql/config/:/etc/mysql/conf.d -v D:/test/mysql/data/:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root --name lkmysql mysql:8.0.23
# 启动成功之后,我们在本地使用navicat测试一下
# navicat 连接到本地的 3310 和 容器的3306映射,这个时候我们就可以连上了
假设我们将容器删除,发现,我们挂载到本地的数据卷依旧没有丢失,这就实现了容器数据的持久功能!
4、具名和匿名挂载
# 匿名挂载
-v 容器内路径
PS D:\> docker run -d -P --name nginx01 -v /etc/nginx nginx
# 查看所有的 volume 的情况
PS D:\> docker volume ls
DRIVER VOLUME NAME
local 1b6dcf2cdbf88ffbe8683b89b3575cc36fc293e3fa695038f2780b937d1c2700
local 43a9a76d7797b65aedc5199a93fb50ece5a85da5557220b5e6c2aa410d22527f
local 921dd4a1b8b372d37c75b1a8a1dea265ac7492fbf89f2916df259ddaeb7586bc
# 这里发现,这种就是匿名挂载,我们在 -v 只写了容器内的路径,没有写容器外的路径!
# 具名挂载
PS D:\># docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
343e7ed7acdf5cab66718129d463f06c01a0816fd4b78e5201d6c10b5dfadd7d
PS D:\> docker volume ls
DRIVER VOLUME NAME
local 1b6dcf2cdbf88ffbe8683b89b3575cc36fc293e3fa695038f2780b937d1c2700
local 43a9a76d7797b65aedc5199a93fb50ece5a85da5557220b5e6c2aa410d22527f
local 921dd4a1b8b372d37c75b1a8a1dea265ac7492fbf89f2916df259ddaeb7586bc
local juming-nginx
# 通过 -v 卷名:容器内路径
# 查看一下这个卷

所有的docker容器内的卷,没有指定目录的情况下都是在 /var/lib/docker/volumes/xxx/_data
我们通过具名挂载可以方便的找到我们的一个卷,大多数情况在使用具名挂载
# 任何确定是具名挂载还是匿名挂载,还是指定路径挂载!
-v 容器内路径 #匿名挂载
-v 卷名:容器内路径 #具名挂载
-v /宿主机路径:容器内路径 #指定路径挂载
拓展:
# 通过 -v 容器内路径:ro rw 改变读写权限
ro readonly # 只读
rw readwrite # 可读可写
# 一旦这个设置了容器权限,容器对我们挂载出来的内容就有限定了
# ro 只要看到ro就说明这个路径只能通过宿主机来操作,容器内部是无法操作的!
5、初识Dockerfile
Dockerfile 就是用来构建doker 镜像的构建文件! 命令脚本! 先体验一下!
通过这个脚本可以生成镜像,镜像是一层一层的,脚本一个个的命令,每个命令都是一层!
# 创建一个dockerfile文件,名字可以随机 建议Dockerfile
# 文件中的内容 指令(大写) 参数
FROM centos
VOLUME ["volume01","volume02"]
CMD echo "----end----"
CMD /bin/bash
# 这里的每个命令,就是镜像的一层!
[+] Building 0.2s (5/5) FINISHED
=> [internal] load build definition from dockerfile.TXT 0.1s
=> => transferring dockerfile: 129B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/centos:latest 0.0s
=> [1/1] FROM docker.io/library/centos 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:231feafd3348cc7cb6a2eeed8b19effe7b15fd2a723a287669e6d06e35aa6261 0.0s
=> => naming to docker.
查看一下卷挂载的具体目录

测试一下刚才的文件是否同步出去了!
这种方式我们未来使用的十分多,因为我们通常会构建自己的镜像!
假设构建镜象是没有挂载卷,要手动镜像挂载 -v 卷名:容器内路径!
数据卷容器
多个mysql 同步数据

# 启动三个容器,通过我们刚才自己写的镜像启动

# 容器二挂载容器一
PS D:\test># docker run -it --name docker02 --volumes-from docker01 lk/centos:1.0
# 测试,改变容器二,容器一则会同步相应的内容,实现了两个容器后之间的数据同步
多个mysql实现数据共享
PS D:\test># docker run -d -p 3310:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:8.0.23
PS D:\test># docker run -d -p 3311:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:8.0.23
# 这个时候,可以实现两个容器数据同步!
结论:
容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止
但是一旦你持久化到了本地,这个时候,本地的数据是不会删除的
八、DockerFile
1、DockerFile介绍
dockerfile 是用来构建docker镜像的文件! 命令参数脚本!
构建步骤:
1、编写一个dockerfile 文件
2、docker build 构建成为一个镜像
3、docker run 运行镜像
4、docker push 发布镜像 (DockerHub、阿里云镜像仓库)
很多官方镜像都是基础包,很多功能没有,我们通常会自己搭建自己的镜像!
官方既然可以制作镜像,那我们也可以!
2、DockerFile构建过程
基础知识:
1、每个保留关键字(指令)都是必须是大写字母
2、执行从上到下顺序执行
3、#表示注释
4、每一个指令都会创建提交一个新的镜像层,并提交!
dockerfile是面向开发的,我们以后要发布项目,做镜像,就需要编写dockerfile文件,这个文件十分简单!
Docker镜像逐渐成为企业交付的标准,必须要掌握!
步骤:开发、部署、运维...缺一不可!
DockerFile:构建文件,定义了一切的步骤,源代码
DockerImages:通过DockerFile构建生成的镜像,最终发布和运行的产品!
Docker容器:容器就是镜像运行起来提供服务的
3、DockerFile的指令
FROM # 基础镜像,一切从这里开始构建
MAINTAINER # 竟像是谁写的,姓名+邮箱
RUN # 镜像构建的时候需要运行的命令
ADD # 步骤:tomcat镜像,这个tomcat压缩包!添加内容
WORKDIR # 镜像的工作目录
VOLUME # 挂载的目录
EXPOSE # 保留的端口配置
CMD # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD # 当构建一个被继承 DockerFile 这个时候就会运行 ONBUILD 的指令,触发指令
COPY # 类似ADD ,将我们文件拷贝到镜像中
ENV # 构建的时候设置环境变量
创建一个自己的centos
# 1、编写DockerFile的文件
PS D:\test> cat .\mydockerfile-centos.TXT
FROM centos
MAINTAINER lk<2568216213@qq.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "----end----"
CMD /bin/bash
# 2、通过这个文件构建镜像
# 命令 docker build -f dockerfile文件路径 -t 镜像名:[tag]
PS D:\test># docker build -f .\mydockerfile-centos.TXT -t mycentos:0.1 .
# 3、测试运行
对比:之前的原生的centos

我们可以列出本地进行的变更历史
docker history 镜像id

我们平时拿到一个镜像,可以研究一下它是怎么做的了
CMD 和 ENTRYPOINT 区别
CMD # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令
Dockerfile中很多命令都十分的相似,我们需要了解它们的区别
4、实战:Tomcat镜像
1、准备镜像文件 tomcat 压缩包 .jdk 的压缩包
2、编写dockerfile文件,官方命名Dockerfile,build 会自动寻找这个文件,就不需要-f指定了!
FROM centos
MAINTAINER lk<2568216213@qq.com>
COPY readme.txt /usr/local/readme.txt
ADD jdk-8u281-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.43.tar.gz /usr/local/
RUN yum -y install vim
ENV MYPATH /usr/local
WORKDIR $MYPATH
ENV JAVA_HOME /usr/local/jdk1.8.0_281
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.43
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.43
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
EXPOSE 8080
CMD /usr/local/apache-tomcat-9.0.43/bin/startup.sh && tail -F /url/local/apache-tomcat-9.0.43/bin/logs/catalina.out
3、构建镜像
PS D:\test\tomcat_test># docker build -f .\Dockerfile.txt -t diytomcat:0.1 .
4、启动镜像
PS D:\test\tomcat_test># docker run -d -p 9090:8080 --name lktomcat -v D:/test/tomcat_test/lk/build/tomcat/test:/usr/local/apache-tomcat-9.0.43/webapps/test -v D:/test/tomcat_test/lk/build/tomcat/tomcatlogs/:/usr/local/apache-tomcat-9.0.43/logs diytomcat:0.1
5、访问测试
6、发布项目(由于做了卷挂载,我们直接在本地编写项目就可以发布了!)
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
</web-app>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>菜鸟教程</title>
</head>
<body>
<%
out.println("Hello World!");
%>
</body>
</html>
5、发布自己的镜像
DockerHub
1、地址 :https://hub.docker.com/ 注册自己的账号
2、确定这个账号可以登录
3、在我们服务器上提交自己的镜像
PS D:\test\tomcat_test># docker login --help
Log in to a Docker registry or cloud backend.
If no registry server is specified, the default is defined by the daemon.
Usage:
docker login [OPTIONS] [SERVER] [flags]
docker login [command]
Available Commands:
azure Log in to azure
Flags:
-h, --help Help for login
-p, --password string password
--password-stdin Take the password from stdin
-u, --username string username
Use "docker login [command] --help" for more information about a command.
4、登录完毕后就可以提交镜像了
PS D:\test\tomcat_test># docker login -u lk990528
Password:
Login Succeeded
PS D:\test\tomcat_test># docker push lk990528/diytomcat:0.1
The push refers to repository [docker.io/lk990528/diytomcat]
5f70bf18a086: Pushed
9cd980cc6628: Pushed
02c1fd3315ac: Pushed
f6ca1bf2c604: Pushed
7ccce8718bdb: Pushed
2653d992f4ef: Pushed
0.1: digest: sha256:12bd99822cc0e137aa3216aa818e2a76d5624de5a97ab2b20a9e6c1939782466 size: 1579
注意:推送的镜像前面需要加上username,这样才能顺利推送
九、理解网络
原理
我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了docker,就会有一个网卡docker0
桥接模式,使用的就是 evth-pair 技术!
# 容器的网卡都是一对一对的
# evth—pair 就是一对的虚拟设备接口,他们都是成对出现的,一端连接着协议,一端彼此相连
# 正因为有这个特性,evth-pair 充当了一个桥梁,连接各种虚拟网络设备
所有的容器不指定网络的情况下,都是docker0 路由,docker会给我们的容器分配一个默认的可用ip。
只要容器删除,对应网桥一对就没了!
--link
思考一个场景,我们编写了一个微服务,database url = ip ,项目不重启,数据库ip换掉了,我们希望可以处理这个问题,可以通过名字来进行访问容器
PS C:\Users\Administrator># docker exec -it tomcat02 ping tomcat01
ping: tomcat01: Name or service not known
# 如何可以解决 通过名字来访问的问题呢?
PS C:\Users\Administrator># docker run -d -P --name tomcat03 --link tomcat02 tomcat
PS C:\Users\Administrator># docker exec -it tomcat03 ping tomcat02
PING tomcat02 (172.17.0.3) 56(84) bytes of data.
64 bytes from tomcat02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.237 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.068 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=3 ttl=64 time=0.117 ms
# 反向可以ping通吗
PS C:\Users\Administrator># docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Name or service not known
其实这个tomcat03 就是在本地配置了tomcat02的配置?
# 查看 hosts 配置,在这里原理发现
PS C:\Users\Administrator># docker exec -it tomcat03 cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.3 tomcat02 e2773fff5717
172.17.0.4 8005db20af43
--link 就是给我们在hosts配置中增加了一个 172.17.0.3 tomcat02 e2773fff5717
我们现在完Docker 已经不建议使用 --link 了!
自定义网络! 不适用docker0!
docker0问题:不支持容器名连接访问!
自定义网络
查看所有的docker网咯

网络模式
bridge:桥接 docker (默认,自己床架也使用bridge 模式)
none:不配置网络
host:和宿主机共享网络
container:容器网络连通!(用的少!局限很大)
测试
# 我们直接启动的命令 --net bridge 而这个就是我们的docker0
docker run -d -P --name tomcat01 tomcat
docker run -d -P --name tomcat01 --net bridge tomcat
# docker0 特点,默认,域名不能访问, --link 可以打通连接!
# 我们可以自定义一个网络!
PS C:\Users\Administrator># docker network create --driver bridge --subnet 192.167.0.0/16 --gateway 192.167.0.1 mynet01
3d661bd60b135ddab3c6ada51b18aefc46e70de671e22d8d0e91dacba4db32c7

PS C:\Users\Administrator># docker run -d -P --name tomcat-net-01 --net mynet01 tomcat
93c4f8377eb2be3d059b072a845dd383ccf791c88f894d8d107b387abc194d84
PS C:\Users\Administrator># docker run -d -P --name tomcat-net-02 --net mynet01 tomcat
58a98c98ac87de3f00141344bd2cba3f9a1b8657c762705c342bce39bf97c0fe
PS C:\Users\Administrator># docker inspect mynet01
[
{
"Name": "mynet01",
"Id": "3d661bd60b135ddab3c6ada51b18aefc46e70de671e22d8d0e91dacba4db32c7",
"Created": "2021-03-19T09:52:34.575918Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.167.0.0/16",
"Gateway": "192.167.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"58a98c98ac87de3f00141344bd2cba3f9a1b8657c762705c342bce39bf97c0fe": {
"Name": "tomcat-net-02",
"EndpointID": "319aea435d9e0819f3d63ed7f61f362e3537c9a0bd62345a7b827fde88ea6f40",
"MacAddress": "02:42:c0:a7:00:03",
"IPv4Address": "192.167.0.3/16",
"IPv6Address": ""
},
"93c4f8377eb2be3d059b072a845dd383ccf791c88f894d8d107b387abc194d84": {
"Name": "tomcat-net-01",
"EndpointID": "e49bf00c331389f6f84f7767f8acbc8eb2df7e93aba350f6ff50ca3ddaefcdf1",
"MacAddress": "02:42:c0:a7:00:02",
"IPv4Address": "192.167.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
# 再次测试ping连接
PS C:\Users\Administrator># docker exec -it tomcat-net-01 ping 192.167.0.3
PING 192.167.0.3 (192.167.0.3) 56(84) bytes of data.
64 bytes from 192.167.0.3: icmp_seq=1 ttl=64 time=0.184 ms
64 bytes from 192.167.0.3: icmp_seq=2 ttl=64 time=0.073 ms
64 bytes from 192.167.0.3: icmp_seq=3 ttl=64 time=0.091 ms
64 bytes from 192.167.0.3: icmp_seq=4 ttl=64 time=0.101 ms
read escape sequence
PS C:\Users\Administrator># docker exec -it tomcat-net-01 ping tomcat-net-02
PING tomcat-net-02 (192.167.0.3) 56(84) bytes of data.
64 bytes from tomcat-net-02.mynet01 (192.167.0.3): icmp_seq=1 ttl=64 time=0.089 ms
64 bytes from tomcat-net-02.mynet01 (192.167.0.3): icmp_seq=2 ttl=64 time=0.080 ms
64 bytes from tomcat-net-02.mynet01 (192.167.0.3): icmp_seq=3 ttl=64 time=0.071 ms
read escape sequence
我们自定义的网络docker都已经帮我们维护好对应的关系,推荐我们平时这样使用网络!
好处:
redis- 不同的集群使用不同的网络,保证集群是安全和健康的
mysql- 不同的集群使用不同的网咯,保证集群是安全和健康的
假设要跨网络操作别人,就需要使用 docker network connect 连通!
PS C:\Users\Administrator># docker exec -it tomcat01 ping tomcat-net-01
ping: tomcat-net-01: Name or service not known
PS C:\Users\Administrator># docker network connect mynet01 tomcat01
PS C:\Users\Administrator># docker exec -it tomcat01 ping tomcat-net-01
PING tomcat-net-01 (192.167.0.2) 56(84) bytes of data.
64 bytes from tomcat-net-01.mynet01 (192.167.0.2): icmp_seq=1 ttl=64 time=0.133 ms
64 bytes from tomcat-net-01.mynet01 (192.167.0.2): icmp_seq=2 ttl=64 time=0.060 ms
64 bytes from tomcat-net-01.mynet01 (192.167.0.2): icmp_seq=3 ttl=64 time=0.135 ms
小结

命令总结:
# 显示信息
docker version # 显示docker的版本信息
docker info # 显示docker的系统信息,包括镜像和容器的数量
docker 命令 --help # 显示帮助信息
docker logs -tf --tail 10 dce7b86171bf # 查看日志
docker top 容器id # 查看容器中进程信息
docker inspect 容器id # 查看镜像中的元数据
docker history 镜像id # 列出本地镜像的变更历史
# 镜像相关
docker images # 查看所有本地的主机上的镜像
docker search mysql --filter=STARS=3000 # 搜索镜像
docker rmi -f 容器id # 删除指定的镜像
docker rmi -f ${docker images -aq} # 删除全部的镜像
docker pull mysql # 下载镜像
docker commit -a="lk" -m="add webapps app" a1170d0a51f2 tomcat02:1.0 # commit镜像
# 容器相关
docker run -it centos /bin/bash # 启动并进入容器
exit # 从容器中退回主机
ctrl + P + Q # 容器不停止退出
docker ps # 列出当前正在运行的容器
docker rm 容器id # 删除指定的容器,不能删除正在运行的容器,如果要强制删除 rm -f
docker rm -f $(docker ps -aq) # 删除所有的容器
docker start 容器id # 启动容器
docker restart 容器id # 重启容器
docker stop 容器id # 停止当前正在运行的容器
docker kill 容器id # 强制停止当前容器
docker run -d centos # 后台启动容器
docker exec -it 容器id /bin/bash # 进入当前正在运行的容器
docker attach 容器id # 进入当前正在运行的容器
docker cp 容器id:容器内路径 目的的主机路径 # 从容器内拷贝文件到主机上
docker build -f dockerfile文件路径 -t 镜像名:[tag] . # 构建镜像
docker push 用户名/镜像名:tag # 提交镜像
# 挂载
docker run -it -v 主机目录:容器目录 # 宿主机和容器挂载
-v 容器内路径 #匿名挂载
-v 卷名:容器内路径 #具名挂载
-v /宿主机路径:容器内路径 #指定路径挂载
# 通过 -v 容器内路径:ro rw 改变读写权限
ro readonly # 只读
rw readwrite # 可读可写
docker run -it --name 容器名1 --volumes-from 容器名2 镜像名 # 容器之间挂载
# 用户
docker login -u 用户名 # 登录
docker logout # 退出登录
# 网络
docker network ls # 查看网络
docker network inspect e2803a6cf926 # 查看网络详情
docker network create --driver bridge --subnet 192.167.0.0/16 --gateway 192.167.0.1 mynet01 # 自定义网络mynet01
docker run -d -P --name tomcat-net-01 --net mynet01 tomcat # 将容器放到自定义网络中
docker network connect mynet01 tomcat01 # 跨网络连接

浙公网安备 33010602011771号