认识docker以及如何使用
Docker是一款针对程序开发人员和系统管理员来开发、部署、运行应用的一款虚拟化平台。Docker 可以让你像使用集装箱一样快速的组合成应用,并且可以像运输标准集装箱一样,尽可能的屏蔽代码层面的差异。传统虚拟化方式是在硬件层面实现虚拟化,需要有额外的虚拟机管理应用和虚拟机操作系统层。而docker容器是在操作系统层面上实现虚拟化,直接复用本地主机操作系统,更加轻量。
docker
Docker Engine概述
Docker Engine是一种开源容器化技术,用于构建和容器化您的应用程序。Docker Engine通过以下方式充当客户端-服务器应用程序:
- 具有长时间运行的守护进程的服务器
dockerd。 - API,用于指定程序可以用来与Docker守护程序进行对话和指示的接口。
- 命令行界面(CLI)客户端
docker。
为什么选择Docker?
快速交付应用程序
- 我们希望你的开发环境能够更好的提高你的工作效率。Docker容器能够帮助开发人员、系统管理员、QA和版本控制工程师在一个生产环节中一起协同工作。我们制定了一套容器标准,而这套容器标准能够使系统管理员更改容器的时候,程序员不需要关心容器的变化,而更专注自己的应用程序代码。从而隔离开了开发和管理,简化了开发和部署的成本。
- 我们使应用的构建方式更加简单,可以快速的迭代你的应用,并且可以可视化的来查看应用的细微更改。这能够帮助组织里边的成员来更好的理解一个应用从构建到运行的过程。
- Docker 是一个轻量级的容器,所以它的速度是非常快的,而容器的启动时间只需要一秒钟,从而大大的减少了开发、测试和部署的时间。轻松部署和扩展
- Docker 容器可以运行在大多数的环境中,你可以在桌面环境、物理主机、虚拟主机再到数据中,私有或者公有云中部署。
- 因为 Docker 可以从多平台下运行。你可以很容器的迁移你的应用程序。如果需要,你可以非常简单的将应用程序从测试环境迁移到云,或者从云迁移到测试环境。
- Docker 是一个轻量级的容器,因此它可以在很短的时间内启动和关闭。当你需要的时候,你可以启动多个容器引擎,并且在不需要使用他们的时候,可以将他们全部关闭。
Docker的容器本身不需要额外创建虚拟机管理系统,因此你可以启动多套Docker容器,这样就可以充分发挥主机服务器的物理资源,也可以降低因为采购服务器licenses而带来的额外成本。
快速构建 轻松管理
因为Docker上述轻便,快速的特性。可以使您的应用达到快速迭代的目的。每次小的变更,马上就可以看到效果。而不用将若干个小变更积攒到一定程度再变更。每次变更一小部分其实是一种非常安全的方式。
镜像
概念
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。
加载原理
(1)UnionFS(联合文件系统)
UnionFS(联合文件系统):Union文件系统是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下,Union文件系统是Dokcer镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的镜像。
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统加载起来,这样最终的文件系统会包含所有的底层文件和目录。
(2)Docker镜像加载原理
docker的镜像实际上是由一层一层的文件系统构成,这种层级的文件系统UnionFS。
主要包含bootloader和kernel,bootloader主要是引导加载kernel,Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的linux/unix系统是一样的,包含boot加载器内核。当boot加载完之后整个内核就都在内存中了,此时内存的使用权已经由bootfs交给内核了,此时系统也会卸载bootfs。
rootfs:在 bootfs之上,包含的就是典型 Linux系统中的/dev、/proc、/bin、/etc等标准目录和文件,rootfs就是各种不同的操作系统发行版,比如:Ubuntu,、CentOS等等
简单理解:
- 对于Docker安装OS来说:就是Docker使用了Linux本身的bootfs,只需要安装自己所需的rootfs。
- 对于Docker安装普通镜像来说:就是Docker本身是分层下载镜像,所以可以提取出公共层镜像,进行复用。
可以看到,新镜像是从 base 镜像一层一层叠加生成的。每安装一个软件,就在现有镜像的基础上增加一层。为什么 Docker 镜像要采用这种分层结构呢?
最大一个好处就是——共享资源
比如:有多个镜像都从相同的base镜像构建而来,那么宿主机只需要在磁盘上保存一份base镜像,同时内存中也需要加载一份base镜像,就可以为所有服务器服务了。而且镜像的每一层都可以被共享。
平时我们安装进虚拟机的CentOS都是好几个G,为什么docker这里才200M?
对以一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就行,因为底层直接用host和kernel,自己只需要提供rootfs就行。由此可见对于不同的Linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以公用bootfs。
下图是docker下载镜像的日志,可以很清晰的看到是一层一层在下载的。
容器命令
进入容器内部:docker run -it rongqiName/rongqiId /bin/bash
退出容器:exit
容器生命周期管理
- run: https://www.runoob.com/docker/docker-run-command.html
- start/stop/restart: https://www.runoob.com/docker/docker-start-stop-restart-command.html
- kill: https://www.runoob.com/docker/docker-kill-command.html
- rm: https://www.runoob.com/docker/docker-rm-command.html
- pause/unpause: https://www.runoob.com/docker/docker-pause-unpause-command.html
- create:https://www.runoob.com/docker/docker-create-command.html
- exec:https://www.runoob.com/docker/docker-exec-command.html
容器操作
- ps:https://www.runoob.com/docker/docker-ps-command.html
- inspect:https://www.runoob.com/docker/docker-inspect-command.html
- top:https://www.runoob.com/docker/docker-top-command.html
- attach:https://www.runoob.com/docker/docker-attach-command.html
- events:https://www.runoob.com/docker/docker-events-command.html
- logs:https://www.runoob.com/docker/docker-logs-command.html
- wait:https://www.runoob.com/docker/docker-wait-command.html
- export:https://www.runoob.com/docker/docker-export-command.html
- port:https://www.runoob.com/docker/docker-port-command.html
容器rootfs命令
容器数据卷
匿名挂载
docker run -p 8080:80 --name nginx -v /etc/nginx -d nginx
# 查看docker镜像,可以看到刚刚创建的nginx的信息[root@localhost ~]# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES942dba4d602b nginx "/docker-entrypoint.…" 5 minutes ago Up 5 minutes 0.0.0.0:8080->80/tcp nginx
# 查看数据卷列表,可以看到生成了一个随机名称的数据卷[root@localhost ~]# docker volume lsDRIVER VOLUME NAMElocal 4a1a16c05c8653f31cfbaf3d5839f69b734c81dcfb4254ef98f308d95dbe4192
# 查看该数据卷的详细信息[root@localhost ~]# docker volume inspect 4a1a16c05c8653f31cfbaf3d5839f69b734c81dcfb4254ef98f308d95dbe4192[ { "CreatedAt": "2021-04-04T17:17:51+08:00", "Driver": "local", "Labels": null, "Mountpoint": "/var/lib/docker/volumes/4a1a16c05c8653f31cfbaf3d5839f69b734c81dcfb4254ef98f308d95dbe4192/_data", "Name": "4a1a16c05c8653f31cfbaf3d5839f69b734c81dcfb4254ef98f308d95dbe4192", "Options": null, "Scope": "local" }]具名挂载
docker run -p 8081:80 --name nginx1 -v nginx:/etc/nginx -d nginx
# 查看数据卷列表,可以看到生成了一个随机名称的数据卷[root@localhost ~]# docker volume lsDRIVER VOLUME NAMElocal 4a1a16c05c8653f31cfbaf3d5839f69b734c81dcfb4254ef98f308d95dbe4192local nginx
# 查看该数据卷的详细信息[root@localhost ~]# docker volume inspect nginx[ { "CreatedAt": "2021-04-04T17:19:14+08:00", "Driver": "local", "Labels": null, "Mountpoint": "/var/lib/docker/volumes/nginx/_data", "Name": "nginx", "Options": null, "Scope": "local" }]指定路径挂载
docker run -p 8082:80 --name nginx2 -v /mydata/nginx/html:/usr/share/nginx/html -v /mydata/nginx/logs:/var/log/nginx -d nginx数据同步
—volumes-from ps:因为使用的是拷贝,当一个容器删除后,另一个容器中的数据不会消失。
Dockerfile
FROM # 基础镜像,第一条指令必须为 FROM 指令。并且,如果在同一个Dockerfile中创建多个镜像时,可以使用多个 FROM 指令(每个镜像一次)MAINTAINER # 指定维护者信息,一般是姓名 + 邮箱RUN # 镜像构建的时候需要的命令ADD # 压缩文件放在当前目录下,拷过去会自动解压WORKDIR # 镜像工作目录VOLUME # 挂载的目录EXPOSE # 暴露的端口CMD # 指定容器启动时要运行的命令,如果有多个该命令,只有最后一个生效,可被替代ENTRYPOINT # 指定容器启动时要运行的命令,可以追加命令ONBUILD # 当构建一个被继承 DockerFile ,这个时候就会运行 ONBUILD 的指令,触发命令COPY # 类似ADD,将我们的文件拷贝到容器中,当使用本地目录为源目录时,推荐使用ENV # 指定一个环境变量Docker网络
docker0
docker pull 348491564/sentinel-dashboard:1.8.1
docker run -d -it -p 8858:8858 --name sentinel1 -v /mydata/sentinel/logs:/root/logs 348491564/sentinel-dashboard:1.8.1
docker run -d -it -p 8859:8858 --name sentinel2 -v /mydata/sentinel/logs:/root/logs 348491564/sentinel-dashboard:1.8.1
# 为容器安装ip addr命令和ping命令apt-get install iproute2
[root@localhost ~]# ip addr1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:5a:e2:81 brd ff:ff:ff:ff:ff:ff inet 192.168.1.80/24 brd 192.168.1.255 scope global noprefixroute ens33 valid_lft forever preferred_lft forever inet6 240e:390:c66:8960:822d:8305:95bd:8188/64 scope global noprefixroute dynamic valid_lft 258969sec preferred_lft 172569sec inet6 fe80::6f0d:e285:3e9a:f34d/64 scope link noprefixroute valid_lft forever preferred_lft forever3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:05:60:0b:d4 brd ff:ff:ff:ff:ff:ff inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0 valid_lft forever preferred_lft forever inet6 fe80::42:5ff:fe60:bd4/64 scope link valid_lft forever preferred_lft forever23: veth0a5c9e6@if22: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default link/ether 96:22:79:da:e1:fe brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet6 fe80::9422:79ff:feda:e1fe/64 scope link valid_lft forever preferred_lft forever25: veth52d47f8@if24: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default link/ether aa:6b:a7:71:a6:64 brd ff:ff:ff:ff:ff:ff link-netnsid 1 inet6 fe80::a86b:a7ff:fe71:a664/64 scope link valid_lft forever preferred_lft forever
# 使用容器1 ping 容器2 的ip,可以ping通[root@localhost ~]# docker exec -it sentinel1 ping 172.17.0.3PING 172.17.0.3 (172.17.0.3): 56 data bytes64 bytes from 172.17.0.3: icmp_seq=0 ttl=64 time=0.062 ms64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.049 ms64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.048 ms64 bytes from 172.17.0.3: icmp_seq=3 ttl=64 time=0.046 ms
# 使用容器1 ping 容器2 的域名,无法找到主机[root@localhost ~]# docker exec -it sentinel1 ping sentinel2ping: unknown host自定义Docker网络
[root@localhost ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
docker run -d -it -p 8858:8858 --name sentinel1 -v /mydata/sentinel/logs:/root/logs --net mynet 348491564/sentinel-dashboard:1.8.1
docker run -d -it -p 8859:8858 --name sentinel2 -v /mydata/sentinel/logs:/root/logs --net mynet 348491564/sentinel-dashboard:1.8.1
[root@localhost ~]# docker exec -it sentinel1 ping sentinel2PING 4f7d49a86234 (192.168.0.2): 56 data bytes64 bytes from 192.168.0.2: icmp_seq=0 ttl=64 time=0.050 ms64 bytes from 192.168.0.2: icmp_seq=1 ttl=64 time=0.045 ms64 bytes from 192.168.0.2: icmp_seq=2 ttl=64 time=0.046 ms64 bytes from 192.168.0.2: icmp_seq=3 ttl=64 time=0.048 ms64 bytes from 192.168.0.2: icmp_seq=4 ttl=64 time=0.047 ms64 bytes from 192.168.0.2: icmp_seq=5 ttl=64 time=0.039 ms64 bytes from 192.168.0.2: icmp_seq=6 ttl=64 time=0.062 msDocker-compose
介绍
Docker-Compose 是 Docker 的一种编排服务,是一个用于在 Docker 上定义并运行复杂应用的工具,可以让用户在集群中部署分布式应用。通过 Docker-Compose 用户可以很容易地用一个配置文件定义一个多容器的应用,然后使用一条指令安装这个应用的所有依赖,完成构建。Docker-Compose 解决了容器与容器之间如何管理编排的问题。
Compose 中有两个重要的概念:
- 服务 (service) :一个应用的容器,实际上可以包括若干运行相同镜像的容器实例。
- 项目 (project) :由一组关联的应用容器组成的一个完整业务单元,在 docker-compose.yml 文件中定义。
一个项目可以由多个服务(容器)关联而成,Compose 面向项目进行管理,通过子命令对项目中的一组容器进行便捷地生命周期管理。
配置
# 版本配置version: '3'
# 服务配置services: service1: ... service2: ...# 其他配置,例如:网卡配置networks: net1: name: net1 driver: bridge net2: name: net2 driver: bridge文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!













