docker engine安装
ubuntu20.04安装docker教程
docker核心架构
镜像(image
)
- 一个镜像就代表一个软件服务(
ubuntu
镜像、mysql
镜像、redis
镜像、mq
镜像) - 只读
远程中心仓库(repository
)
-
中心仓库用来集中存储、管理所有软件服务(镜像文件) === >>>
仓库web界面 docker hub
-
镜像搜索
docker search
与拉取docker pull
下载(拉取后自动存储到本地仓库)
# 除了docker hub搜索,命令行也可搜索
docker search tomcat
# 下载(tomcat:11.0.0 11.0.0为标签,不写默认为latest)
docker pull tomcat:11.0.0
docker pull tomcat:9.0.82-jdk8-corretto
docker pull
默认从官方镜像地址下载,很慢,切回国内备份镜像- 配置国内镜像源,加速下载
# 打开 Docker 配置文件
# Linux:/etc/docker/daemon.json(如果不存在,可以创建)
# 添加如下内容(登陆阿里云获取自己专属的镜像加速服务)
{
"registry-mirrors": ["https://bx6t9g3c.mirror.aliyuncs.com"]
}
# 重新启动docker引擎
sudo systemctl daemon-reload
sudo systemctl restart docker
# 检测查看配置是否成功
docker info
# 输出如下(末尾):
Registry Mirrors:
https://bx6t9g3c.mirror.aliyuncs.com/
Live Restore Enabled: false
参考:
自己的阿里云镜像加速器查找
- 本地仓库:用来存储使用docker过程中的相关镜像(默认位置:
/var/lib/docker
) - 创建自己的私有库
容器(container
)
- 一个镜像运行一次就会产生一个容器,容器就是一个运行的软件服务,简言之:容器是镜像的实例
- 可读可写
- 基于镜像来运行
docker run
容器
docker run -it thicv:v1.0 bash
# --name 给容器命名 -v 挂载本地卷
docker run -it --name planning -v ./planningFigure:/thicvPilot/planningFigure thicv:v1.0 bash
镜像与容器的基本操作! ⭐️ ⭐️
docker运行第一个程序: hello-world
- 安装docker时官方提供了一个默认镜像
hello-world
- 查看本地仓库所有镜像:
docker images
docker images
# output (镜像名称、版本标签、唯一标识ID、创建时间(官方构建时间)、大小)
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat 9.0.82-jdk8-corretto bbaf8bb8e2c9 4 days ago 385MB
thicv v1.0 9d8d9f806797 5 days ago 2.27GB
hello-world latest 9c7a54a9a43c 6 months ago 13.3kB
- 通过镜像创建并运行容器:
docker run
docker run hello-world
# 注:必须要指定具体的镜像及其版本,如hello-world,容器名称是可选项
# 如:
docker run --name Hello hello-world
# output
Hello from Docker!
......
For more examples and ideas, visit:
https://docs.docker.com/get-started/
注:docker run
IMAGE
先会在本地仓库去找IMAGE
,如若没找到会去中心仓库尝试下载拉取
- 基础镜像
rootfs
- 注意点 🌟
docker pull centos:latest
docker run -d --name test01 centos:latest
docker ps
# 后台没有运行的容器
# 原因是:镜像中没有可执行服务
# 可以理解为:系统启动后没有运行的可执行程序,然后自己又关机了
docker run -it --name test02 centos:latest
辅助命令
命令 | 功能 |
---|---|
**docker -v **或者 docker --version | 查询docker engine客户端版本 |
docker version | 查看客户端与服务端部分信息 |
docker info | 查看docker engine详细信息 |
docker --help | 查看docker帮助文档 |
docker [命令] --hlep | 获取docker命令帮助文档 |
docker login/logout | 登入/退出docker hub |
镜像管理基本操作
命令 | 功能 |
---|---|
docker images 或者docker image ls 或者 docker images -a | 查看本地仓库所有镜像 |
docker images [image] | 只查看对应镜像的信息 |
docker search [image] | 在中心仓库检索镜像(只能看是否存在,不能列出版本) |
docker pull [image:TAG] | 从中心仓库拉取镜像(若不指定版本tag,则默认latest) |
docker rmi [image] 或者 docker image rm [image] | 删除本地仓库中的镜像[image]可以是name/ID(正常删除,但无法删除已经通过其创建运行容器后的镜像) |
docker rmi -f [image] | 强制删除镜像(不管容器的死活,但并不会删除通过其实例化的容器) |
docker push [image] | 上传镜像 |
docker image inspect [image] | 查看镜像的详细信息 |
docker image prune | 删除所有未被使用的镜像层 |
docker system prune | 删除docker engine中所有未被使用的镜像、容器、数据卷、网络等等,包括通过dockerfile 创建镜像时的缓存 |
扩展:
docker images [image] -q
仅仅列出与image相关的镜像的ID
# 仅仅列出与tomcat相关的镜像的ID
docker images tomcat -q
# output
fb5657adc892
ef6a7c98d192
- 组合操作 强制删除与tomcat相关的所有版本的镜像
# 先执行$里的命令,然后将结果作为参数给外层命令
docker rmi -f $(docker images tomcat -q)
- 检查系统的防火墙状态
systemctl status firewalld.service
容器管理与运行
命令语法:docker 命令 [选项]
(docker 对容器操作可以不写container)
命令 | 功能 |
---|---|
docker ps 或者 docker container ps | 只列出正在运行的容器 |
docker ps -a 或者docker container ps -a | 列出所有容器 |
docker run [image] | 创建并且运行容器 |
docker run --help | 查询选项、参数含义 |
docker rm [container] | 删除已经停止的容器(可以是容器名称/ID;可以多个容器一起删除) |
docker rm -f [container] | 强制删除容器(即使在运行也能) |
docker stop [container] | 停止运行中的容器 |
docker start [container] | 启动已经停止的容器 |
docker restart [container] | 重启容器 |
docker pause [container] | 暂停容器服务 |
docker kill [container] | 杀死容器(杀死进程,stop会允许容器做正常服务的关闭操作,kill是直接杀掉进程) |
docker port [container] | 查看容器的映射端口 |
docker logs [container] | 查看容器日志(-t 加入时间辍;-f 跟随最新的日志打印;–trail n 显示最后n行) |
docker diff [container] | 显示容器内的变化 |
docker stats | 显示容器资源使用情况 |
docker cp containerID:文件路径 宿主机路径 | 从容器拷贝文件到宿主机 |
docker cp 宿主机文件路径 containerID:文件路径 | 拷贝宿主机本地文件到容器中 |
扩展:
- 不论镜像还是容器在操作ID时可指定前几位能够区分即可(如四位)
# 查询所有容器
docker ps -a
# output (容器唯一ID,基于哪个镜像,容器命令,创建时间,当前状态,监听端口,容器名称(若不指定,默认分配独立名称))
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5383edeba808 hello-world "/hello" 8 seconds ago Exited (0) 7 seconds ago Hello
# 删除容器Hello
docker rm Hello
docker rm 5383
- 简单运行一个容器 (这种方式直接运行容器,宿主机无法访问容器内服务,容器是操作系统层面的隔离)
docker run tomcat:8.0
- 创建并运行tomcat容器,同时通过
-p
选项设置容器与宿主机的端口映射关系- 可以同时映射多个端口,如
mq
服务器-p 15672:15672 -p 5672:5672
- 可以同时映射多个端口,如
# --name test01 给容器命名test01,容器名称必须是唯一的
# -p 8080(宿主机):8080(docker容器服务内) 端口映射
docker run --name test01 -p 8080:8080 tomcat:8.0
# 然后网页地址栏目 登陆 宿主机ip:8080 即可显示web页面
http://192.168.0.105:8080/
- 创建并运行tomcat容器,以test02命名该容器,开放端口映射,
-d
以守护进程方式后台启动该服务
docker run --name test02 -p 8082:8080 -d tomcat:8.0
# output (返回容器ID)
530004aec6cd8804b93806f4a62d2201d733e0b782cb80d680760d4f52ede8fc
# 登陆web界面 http://192.168.0.105:8082/
注: 选项的顺序没有要求,但都是在镜像之前
命令 | 功能 |
---|---|
docker attach [container] | 以交互模式进入容器(只能是运行中的容器,退出后,容器也停止不运行) |
docker exec -it [container] | 以交互模式进入容器内部(只能是运行中的容器,退出后容器仍在后台运行) |
- 以交互式方式进入test02容器内部的bash
docker exec -it test02 bash
# bash 进入后打开面板
- 容器与宿主机进行文件传输(记住:最后面的是目标路径)
# 拷贝宿主机本地文件到容器中
docker cp ./Dockerfile test01:/home
# 拷贝容器中文件到宿主机中
docker cp test01:/home/Dockerfile ./temp
- 退出容器
# 在容器内部执行
exit
命令 | 功能 |
---|---|
docker top [container] | 查看容器内运行的进程 |
docker inspect [container] | 查看容器的所有配置及详细信息 |
一个进程代表着一个应用程序的实例。
- 将容器打包成新的镜像
- 容器可读可写, 对容器进行 自己的深度定制
命令 | 功能 |
---|---|
docker commit [container] [image] | 将容器打包成镜像 |
docker save [image] > FILE 或者 docker save [image] -o FILE | 保存本地仓库中的镜像(部署到别的服务器上) |
docker load -i FILE | 还原恢复备份的镜像 |
docker commit -m "描述信息" -a "作者信息" 要打包的容器 镜像名称:标签
# 注意镜像名称要小写
# 创建一个容器tomcat01
docker run -d -p 8081:8080 --name tomcat01 tomcat:8.0
# 将自己定制修改的容器打包提交镜像到本地仓库
# sensiz/tomcat:v2.0 命名及其定义版本标签
docker commit -m "2023.11.10 Modify" -a "sensizlik" tomcat01 sensiz/tomcat:v2.0
docker images
# output
REPOSITORY TAG IMAGE ID CREATED SIZE
sensiz/tomcat v2.0 3431a13ed69e 2 minutes ago 356MB
# 查看镜像的详细信息
docker image inspect sensiz/tomcat:v2.0
-
镜像备份与还原机制
保存本地镜像并将此镜像导入到别的服务器
# sensiz/tomcat:v2.0 本地镜像
# ./temp/myTomCat.tar 保存为tar包文件
docker save sensiz/tomcat:v2.0 -o ./temp/myTomCat.tar
# 在服务器上导入外部打包保存的镜像
docker load -i ./myTomCat.tar
# 查看是否导入成功
docker images
容器中的数据卷管理 volume
-
作用(桥梁):实现容器中的数据(文件和目录)与宿主机中的数据映射(简言之:实现数据同步)
-
docker cp
命令过于繁琐频繁 -
注意:数据卷使用必须在容器首次运行时设置
-
数据卷可以设置多个
-
使用绝对路径/相对路径设置数据卷
这种方式会将容器路径的原始内容全部清空,始终以宿主机路径为主
docker run -v 宿主机绝对路径:容器路径 ...
# -d 以守护进程方式后台运行容器
# -p 端口映射
# -v /home/sensizlik/Docker:/home/docker 本地目录:容器目录 docker目录如果没有可以自动创建
docker run -d -p 8080:8080 -v /home/sensizlik/Docker:/home/docker --name tomcat01 tomcat:8.0
# 也可以将设置成 ro (readonly),代表容器中的文件是只读,且只能修饰容器
docker run -d -p 8080:8080 -v /home/sensizlik/Docker/webapps:/usr/local/tomcat/webapps:ro --name tomcat02 tomcat:8.0
# -it 以交互式方式创建,挂载相对路径且容器路径只读
docker run -it --name tomcat01 -p 8080:8080 -v ./webapps:/usr/local/tomcat/webapps:ro tomcat:8.0 bash
-
使用别名方式设置数据卷
lemon
代表docker数据卷中的别名(如若别名存在,docker直接使用,不存在创建)
-
使用别名方式会保留容器路径原始内容,前提是别名对应路径不能存在内容
- 根据别名创建的数据卷默认在
/var/lib/docker/volumes/
中 - 别名代表一个docker自身维护的数据卷
- 根据别名创建的数据卷默认在
docker run -v lemon:/usr/local/tomcat/webapps:ro ...
docker run -d -p 8080:8080 --name tomcat01 -v lemon:/usr/local/tomcat/webapps tomcat:8.0
# 在宿主机查找以下lemon
find / -name lemon
# output
/var/lib/docker/volumes/lemon
# 切回root用户,即可查看
sudo su
cd /var/lib/docker/volumes/lemon
ls
# output
_data
cd _data
ls
# output
docs examples host-manager manager ROOT
数据卷操作进阶
命令 | 功能 |
---|---|
docker volume create [volume] | 创建一个数据卷 |
docker volume ls | 查看docker维护的本地所有数据卷 |
docker volume inspect [volume] | 查看数据卷详细信息 |
docker volume rm [volume] | 删除数据卷 |
docker volume prune | 删除所有未使用的卷 |
镜像构成原理
-
容器是独立的操作系统(精简linux操作系统+软件服务),是镜像运行的实例
-
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于环境开发的软件,它包含运行某个软件的所有内容,包括代码、运行时所需的库、环境变量和配置文件。
-
联合文件系统
unionFS
- 基础镜像(操作系统核心库+运行环境)
- 一层一层构建
- 一次加载多个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录,在外面看起来,只能看到一个文件系统
- 如:有多个镜像都是从相同的base镜像构建而来的,那么宿主机只需在磁盘中保存一份base镜像,同时内存中也只需加载一份镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。docker 镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称为容器层,容器层之下都叫做镜像层。
高级网络配置(容器间通信之网络使用) ⭐️ ⭐️
容器间通信
说明:容器之间通过网络进行相互通信
- 当 Docker 启动时,会自动在主机上创建一个
docker0
虚拟网桥,实际上是 Linux 的一个 bridge,可以理解为一个软件交换机。它会在挂载到它的网口之间进行转发。
ifconfig
# output
...
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:3c:67:00:55 txqueuelen 0 (以太网)
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
...
-
同时,Docker 随机分配一个本地未占用的私有网段(在 RFC1918 协议中定义)中的一个地址给
docker0
接口。比如典型的172.17.42.1
,掩码为255.255.0.0
。此后启动的容器内的网口也会自动分配一个同一网段(172.17.0.0/16
)的地址。 -
当创建一个 Docker 容器的时候,同时会创建了一对
veth pair
接口(当数据包发送到一个接口时,另外一个接口也可以收到相同的数据包)。这对接口一端在容器内,即eth0
;另一端在本地并被挂载到docker0
网桥,名称以veth
开头(例如vethAQI2QT
)。通过这种方式,主机可以跟容器通信,容器之间也可以相互通信。Docker 就创建了在主机和所有容器之间一个虚拟共享网络。
docker pull tomcat:8.0
docker run --name tomcat01 -p 8081:8080 -d tomcat:8.0
docker run --name tomcat02 -p 8082:8080 -d tomcat:8.0
docker ps
docker inspect tomcat02
docker exec -it tomcat01 bash
root@52935a4d2eb3:/usr/local/tomcat#
# 注释:tomcat01容器内只是开放了8080
curl http://172.17.0.3:8080
总结:
- 默认docker在创建容器时将所有容器都连接到
docker0
网桥上,默认在docker0
网桥的容器都可以使用容器内ip
地址进行通信;- 但是容器重启时,
ip
是动态分配的
- 但是容器重启时,
- 也可以使用容器的名称作为容器的
ip
地址进行通信;- 注意:使用容器名称必须自定义网桥不能使用默认
docker0
- 为了解决一个默认网桥出现瓶颈、拥堵;为自己的项目搭桥
- 注意:使用容器名称必须自定义网桥不能使用默认
docker 网络管理基本操作
命令 | 功能 |
---|---|
docker network ls | 列出可用网络 |
docker network inspect [network] | 查看网络详细信息 |
docker create [network] | 创建一个新的网络 |
docker network connect [network] [container] | 将容器连接到网络 |
docker network disconnect [network] [container] | 将容器从网络断开 |
docker network rm [network] | 删除网络 |
docker network prune | 删除所有未用到的网络 |
自定义网桥实现网桥容器间通信
- docker 中的网桥类型:
bridge
、host
、none
docker network ls
# output
NETWORK ID NAME DRIVER SCOPE
731fabe34f98 bridge bridge local
088206ae6f43 host host local
6d1dc3ad4243 none null local
- 创建网络自定义桥
docker network create ems
# 上面等价于 docker network create -d bridge ems
# 不写,默认网桥类型为bridge
-
在指定的同一个网络中运行多个容器
- 启动容器时明确指定网络(前提是指定的网络已经存在);
# --network ems 指定ems,前提是ems已经存在 docker run -d --name tomcat01 -p 8081:8080 --network ems tomcat:8.0 docker run -d --name tomcat02 -p 8082:8080 --network ems tomcat:8.0 # 查看网络中的容器有哪些(字段:"Containers) docker network inspect ems # 在容器tomcat02中用容器名访问tomcat01 docker exec -it tomcat02 bash curl http://tomcat01:8080
- 启动之后将容器加入到某个网络中
# 创建tomcat03 docker run -d --name tomcat03 -p 8083:8080 tomcat:8.0 # 将tomcat03加入到ems网络中 docker network connect ems tomcat03 # 查看ems中有哪些容器 docker network inspect ems
docker 使用实战
运行MySQL
服务
- docker hub
# 下载镜像
docker pull mysql:5.6
- 创建容器,启动
mysql
开放端口映射(3306)、指定root用户密码
# -e 参数,指定环境变量
docker run --name mysql01 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.6
# always=--restart docker引擎重启后自动重启容器
# -v 数据卷持续化数据到宿主机
docker run --name mysql02 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 --restart=always -v ./mydata:/var/lib/mysql -d mysql:5.6
- 进入容器
dcoker exec -it mysql01 bash
mysql -u root -p
# input 123456