Docker 容器虚拟化技术和自动化部署
Docker 容器虚拟化技术和自动化部署
- 一、Docker 核心组件
- 1.1 Docker 引擎
- 1.2 Docker 镜像
- 1.3 Docker 容器
- 1.4 Docker 仓库
- 二、Docker 环境安装
- 清华镜像安装
- 三、Docker 基本操作
- 3.1 镜像管理
- 3.1.1 查看本地镜像 docker images
- 3.1.2 添加镜像标签 docker tag
- 3.1.3 查看镜像信息 inspect、history
- 3.1.4 镜像导出 save、导入load
- 3.1.5 拉取镜像 docker pull
- 3.1.6 删除本地镜像 docker [image] rmi
- 3.1.7 悬空镜像、删除悬空镜像
- 3.1.8 上传镜像 docker push
- 3.2 容器管理
- 3.2.1 创建与启动容器 create、start、run
- 3.2.2 查看所有容器 docker ps
- 3.2.3 终止运行容器 stop 、kill
- 3.2.4 进入容器内部 docker exec
- 3.2.5 查看容器信息 inspect、stats
- 3.2.6 查看容器日志 docker logs
- 3.2.7 容器文件传输 docker cp
- 3.2.8 删除容器 docker rm
- 3.3 仓库管理
- 3.3.1 登录仓库 docker login
- 3.3.2 登出仓库 docker logout
- 3.3.3 认证文件
- 3.4 命令图谱
- 3.5 部署示例
- 3.5.1 拉取 redis7.4.2 镜像
- 3.5.2 安装MySQL
- 3.5.3 安装Tomcat
- 四、Dicker 核心原理
- 4.1 容器生命周期
- 4.2 容器命名空间
- 4.2.1 进程命名空间(PID namespace)
- 4.2.2 网络命名空间(network namespace)
- 4.2.3 IPC命名空间(IPC namespace)
- 4.2.4 挂载命名空间(Mount namespace)
- 4.2.5 UTS命名空间(UTS namespace)
- 4.2.6 用户命名空间(User namespace)
- 4.3 资源配额限制
- 4.3.1 CPU
- 4.3.2 内存
- 4.3.3 磁盘读写
- 4.4 联合文件系统
- 4.4.1 Docker存储
- 4.4.2 多种文件系统比较
- 4.5 容器网格管理
- 4.5.1 Bridge 网络模式
- 4.5.2 Host 网络模式
- 4.5.3 Container 网络模式
- 4.5.4 None 网络模式
- 4.5.5 Docker 外部访问容器
- 4.5.5.1 映射所有端口地址
- 4.5.5.2 映射到指定地址的指定端口
- 4.5.5.3 映射到指定地址的任意端口
- 4.5.5.4 查看映射端口配置
- 4.5.6 Docker 容器互联
- 4.5.7 Docker 配置DNS
- 4.6 容器数据管理
- 4.6.1 数据管理命令
- 4.6.2 数据卷实战
- 4.6.3 数据卷容器实战
- 4.6.4 tmpfs 挂载
- 4.6.5 数据卷备份还原
- 4.7 实战案例
一、Docker 核心组件
链接: docker官网
Docker是一个 开源 的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可抑制的容器中,然后发布到任何流行的Linux机器上,也可以实现 虚拟化 。
docker和容器技术和虚拟机技术,都是虚拟化技术
docker有着比虚拟机更少的抽象层
1.1 Docker 引擎
Docker 引擎是一个包含以下主要组件的客户端服务器应用程序。
- 一种服务器,它是一种称为守护进程并且长时间运行的程序。
- REST API 用于指定程序可以用来与守护进程通信的接口,并指示它做什么。
- 一个有命令行界面 (CLI) 工具的客户端。
Docker 客户端是用户与 Docker 交互的主要方式,与 Docker 守护进程(Docker引擎)进行通信。
1.2 Docker 镜像
Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。
1.3 Docker 容器
容器是镜像的一个运行实例。
容器可以被创建、启动、开始、停止、删除、暂停等,而这些容器都是彼此相互隔离的、互不可见的。可以把容器看做是一个简易版的 Linux 系统环境(包括root用户权限、进程空间、用户空间和网络空间等)以及运行在其中的应用程序打包而成的盒子。
1.4 Docker 仓库
Docker 仓库类似于代码仓库,它是 Docker 集中存放镜像文件的场所。(官方存放docker的仓库:hub.docker.com)
二、Docker 环境安装
- 配置宿主机网卡转发
# 查看是否有仓库
[root@docker ~]# dnf repolist
Updating Subscription Management repositories.
Unable to read consumer identityThis system is not registered with an entitlement server. You can use "rhc" or "subscription-manager" to register.repo id repo name
AppStream AppStream
BaseOS BaseOS
[root@docker ~]# vim /etc/sysctl.d/docker.conf
[root@docker ~]# cat /etc/sysctl.d/docker.conf
net.bridge.bridge-nf-call-ip6tables=1
net.bridge.bridge-nf-call-iptables=1
net.ipv4.ip_forward=1
清华镜像安装
- 清华镜像安装方法
1. 先执行dnf remove
2. 安装必要的一些系统工具
yum install -y yum-utils
3. 添加软件源信息
yum-config-manager --add-repo https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/rhel/docker-ce.repo
4. 安装Docker
yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
5. 开启Docker服务
systemctl enable --now docker
# 查看是否挂载
[root@docker ~]# mount /dev/sr0 /mnt
mount: /mnt: WARNING: source write-protected, mounted read-only.# 1.先执行dnf remove
[root@docker ~]# dnf remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine \
podman \
runc #以上内容复制粘贴回车,保证没有dockerUpdating Subscription Management repositories.
Unable to read consumer identityThis system is not registered with an entitlement server. You can use "rhc" or "subscription-manager" to register.No match for argument: docker
No match for argument: docker-client
No match for argument: docker-client-latest
No match for argument: docker-common
No match for argument: docker-latest
No match for argument: docker-latest-logrotate
No match for argument: docker-logrotate
No match for argument: docker-engine
No match for argument: podman
No match for argument: runc
No packages marked for removal.
Dependencies resolved.
Nothing to do.
Complete!# 2.安装必要的一些系统工具
[root@docker ~]# yum install -y yum-utils
Updating Subscription Management repositories.
Unable to read consumer identity# 3.添加软件源信息
[root@docker ~]# yum-config-manager --add-repo https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/rhel/docker-ce.repo
Updating Subscription Management repositories.
Unable to read consumer identityThis system is not registered with an entitlement server. You can use "rhc" or "subscription-manager" to register.Adding repo from: https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/rhel/docker-ce.repo #成功[root@docker ~]# ls /etc/yum.repos.d/
dnf.repo docker-ce.repo redhat.repo# 4.安装 Docker
[root@docker ~]# yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Updating Subscription Management repositories.
Unable to read consumer identity#安装成功:
[root@docker ~]# docker -v
Docker version 28.0.4, build b8034c0# 5.开启Docker服务
[root@docker ~]# systemctl enable --now docker
Created symlink /etc/systemd/system/multi-user.target.wants/docker.service → /u sr/lib/systemd/system/docker.service.
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
- 注意:
# 有就改写,没有就创建
[root@docker ~]# vim /etc/docker/daemon.json
[root@docker ~]# cat /etc/docker/daemon.json
{"registry-mirrors": ["https://docker.1ms.run","https://func.ink","https://proxy.1panel.live","https://docker-0.unsee.tech","https://docker.zhai.cm","https://a.ussh.net","https://docker.1ms.run","https://docker.melikeme.cn","https://lispy.org","https://docker.hlmirror.com","https://docker.1panel.live","https://docker.xiaogenban1993.com","https://docker.1panel.top","https://docker.kejilion.pro","https://dockerpull.cn","https://docker.xuanyuan.me","https://docker.anye.in","https://hub.fast360.xyz"]
}
[root@docker ~]# systemctl daemon-reload
[root@docker ~]# systemctl restart docker
[root@docker ~]# docker info | grep "Registry Mirrors" -A 5Registry Mirrors:https://docker.1ms.run/https://func.ink/https://proxy.1panel.live/https://docker-0.unsee.tech/https://docker.zhai.cm/
三、Docker 基本操作
[root@docker ~]# docker --help
Usage: docker [OPTIONS] COMMANDA self-sufficient runtime for containers#通用命令
Common Commands:run Create and run a new container from an imageexec Execute a command in a running containerps List containersbuild Build an image from a Dockerfilepull Download an image from a registrypush Upload an image to a registryimages List imageslogin Authenticate to a registrylogout Log out from a registrysearch Search Docker Hub for imagesversion Show the Docker version informationinfo Display system-wide information#管理命令
Management Commands:builder Manage buildsbuildx* Docker Buildxcompose* Docker Composecontainer Manage containerscontext Manage contextsimage Manage imagesmanifest Manage Docker image manifests and manifest listsnetwork Manage networksplugin Manage pluginssystem Manage Dockertrust Manage trust on Docker imagesvolume Manage volumes #数据卷#编排容器
Swarm Commands:swarm Manage SwarmCommands:attach Attach local standard input, output, and error streams to a running containercommit Create a new image from a container's changescp Copy files/folders between a container and the local filesystemcreate Create a new containerdiff Inspect changes to files or directories on a container's filesystem #判断容器不同点events Get real time events from the serverexport Export a container's filesystem as a tar archivehistory Show the history of an imageimport Import the contents from a tarball to create a filesystem imageinspect Return low-level information on Docker objectskill Kill one or more running containersload Load an image from a tar archive or STDINlogs Fetch the logs of a containerpause Pause all processes within one or more containers #暂停port List port mappings or a specific mapping for the containerrename Rename a containerrestart Restart one or more containersrm Remove one or more containersrmi Remove one or more imagessave Save one or more images to a tar archive (streamed to STDOUT by default) #导出start Start one or more stopped containersstats Display a live stream of container(s) resource usage statisticsstop Stop one or more running containerstag Create a tag TARGET_IMAGE that refers to SOURCE_IMAGEtop Display the running processes of a containerunpause Unpause all processes within one or more containersupdate Update configuration of one or more containerswait Block until one or more containers stop, then print their exit codesGlobal Options:--config string Location of client config files (default "/root/.docker")-c, --context string Name of the context to use to connect to the daemon(overrides DOCKER_HOST env var and default context set with"docker context use")-D, --debug Enable debug mode-H, --host list Daemon socket to connect to-l, --log-level string Set the logging level ("debug", "info", "warn", "error","fatal") (default "info")--tls Use TLS; implied by --tlsverify--tlscacert string Trust certs signed only by this CA (default"/root/.docker/ca.pem")--tlscert string Path to TLS certificate file (default "/root/.docker/cert.pem")--tlskey string Path to TLS key file (default "/root/.docker/key.pem")--tlsverify Use TLS and verify the remote-v, --version Print version information and quitRun 'docker COMMAND --help' for more information on a command.For more help on how to use Docker, head to https://docs.docker.com/go/guides/
docker pull 镜像名:标签
docker images == docker image ls 查看本地镜像
docker ps 查看本地运行中的容器
docker ps -a 查看本地所有容器(-a:all)如果一个字母,就一个“ - ”,完整的单词,就两个“ - ”
docker version 查看安装版本
decker info 查看docker引擎的详细信息
docker rm 容器名称|容器ID
docker run 启动一个容器,如果启动的容器所用到的镜像在本地镜像列表中不存在,则会先拉取该镜像后再运行容器
docker history 镜像名 查看本地指定镜像详细信息
docker inspect 查看镜像的详细信息
给本地镜像打标签:
docker tag [源镜像名:TAG] [目标镜像名:TAG]
3.1 镜像管理
拉取 镜像:docker pull 镜像名称:TAG
查看本地镜像:docker images 、docker image ls、docker image list
导出 镜像到宿主机:docker save 镜像名:标签 -o 文件名称
从宿主机 导入 镜像到docker:docker load -i 文件名称
删除镜像:docker rmi [-f] 镜像名称:标签 | 镜像的ID
查看悬空镜像 docker images -f “dangling=true”
删除悬空镜像 docker image prune
查看镜像历史 docker history 镜像名称:标签
查看镜像信息 docker inspect 镜像名称:标签
3.1.1 查看本地镜像 docker images
docker images
或者
docker image ls
或者
docker image list
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx 1.27.4 4cad75abc83d 2 months ago 192MB
my-nginx 1.27.4 4cad75abc83d 2 months ago 192MB
mysql 8.4.4 4a8a163431d3 2 months ago 769MB
busybox latest ff7a7936e930 6 months ago 4.28MB
[root@docker ~]# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
my-nginx 1.27.4 4cad75abc83d 2 months ago 192MB
nginx 1.27.4 4cad75abc83d 2 months ago 192MB
mysql 8.4.4 4a8a163431d3 2 months ago 769MB
busybox latest ff7a7936e930 6 months ago 4.28MB
[root@docker ~]# docker image list
REPOSITORY TAG IMAGE ID CREATED SIZE
my-nginx 1.27.4 4cad75abc83d 2 months ago 192MB
nginx 1.27.4 4cad75abc83d 2 months ago 192MB
mysql 8.4.4 4a8a163431d3 2 months ago 769MB
busybox latest ff7a7936e930 6 months ago 4.28MB
3.1.2 添加镜像标签 docker tag
docker tag [原镜像名:TAG] [目标镜像名:TAG]
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx 1.27.4 4cad75abc83d 2 months ago 192MB
mysql 8.4.4 4a8a163431d3 2 months ago 769MB
busybox latest ff7a7936e930 6 months ago 4.28MB
[root@docker ~]# docker tag nginx:1.27.4 my-nginx:1.27.4
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
my-nginx 1.27.4 4cad75abc83d 2 months ago 192MB
nginx 1.27.4 4cad75abc83d 2 months ago 192MB
mysql 8.4.4 4a8a163431d3 2 months ago 769MB
busybox latest ff7a7936e930 6 months ago 4.28MB
3.1.3 查看镜像信息 inspect、history
docker inspect NAME[:TAG]
docker history NAME[:TAG]
[root@docker ~]# docker inspect nginx:1.27.4
[{"Id": "sha256:4cad75abc83d5ca6ee22053d85850676eaef657ee9d723d7bef61179e1e1e485","RepoTags": ["my-nginx:1.27.4","nginx:1.27.4"],"RepoDigests": ["nginx@sha256:09369da6b10306312cd908661320086bf87fbae1b6b0c49a1f50ba531fef2eab"],"Parent": "", #父容器"Comment": "buildkit.dockerfile.v0","Created": "2025-02-05T21:27:16Z","DockerVersion": "","Author": "","Config": {"Hostname": "","Domainname": "","User": "","AttachStdin": false,"AttachStdout": false,"AttachStderr": false,"ExposedPorts": {"80/tcp": {} #},"Tty": false,"OpenStdin": false,"StdinOnce": false,"Env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","NGINX_VERSION=1.27.4","NJS_VERSION=0.8.9","NJS_RELEASE=1~bookworm","PKG_RELEASE=1~bookworm","DYNPKG_RELEASE=1~bookworm"],"Cmd": ["nginx","-g","daemon off;"],"Image": "","Volumes": null,"WorkingDir": "","Entrypoint": ["/docker-entrypoint.sh"],"OnBuild": null,"Labels": {"maintainer": "NGINX Docker Maintainers <docker-maint@nginx.com>"},"StopSignal": "SIGQUIT"},"Architecture": "amd64","Os": "linux","Size": 192056179,"GraphDriver": {"Data": {"LowerDir": "/var/lib/docker/overlay2/83c1270b83f96ce5d159b9060ab1f5e6ec800bdd8613c6781bda57580a3edf36/diff:/var/lib/docker/overlay2/cd9fb4c7ba80d4d6ab8e34f6f1440200da2ec13568b20db3ae14f96157c5cf17/diff:/var/lib/docker/overlay2/85d9c1b5be375f39540346bcaa9abd602ba79f47937ec684cdfc1a90a0d2e88d/diff:/var/lib/docker/overlay2/17c15561b5965d77856f3071cc474f7ef79baa7c8891c596692d92aefcbc4472/diff:/var/lib/docker/overlay2/c551fcb932de19264548055b933571afcdf7c7762e2eb47951daf0b5f0c33efc/diff:/var/lib/docker/overlay2/a0967db004b77792f37d5b993144397a8ba1aea4dbdd15ae39023629cfbb4ff5/diff","MergedDir": "/var/lib/docker/overlay2/a3d8b43dd3e4669734f8c5abadd9587b63a23763d4eb2d06e28aafabc76cb2cb/merged","UpperDir": "/var/lib/docker/overlay2/a3d8b43dd3e4669734f8c5abadd9587b63a23763d4eb2d06e28aafabc76cb2cb/diff","WorkDir": "/var/lib/docker/overlay2/a3d8b43dd3e4669734f8c5abadd9587b63a23763d4eb2d06e28aafabc76cb2cb/work"},"Name": "overlay2"},"RootFS": {"Type": "layers","Layers": ["sha256:ea680fbff095473bb8a6c867938d6d851e11ef0c177fce983ccc83440172bd72","sha256:c1a9699c65592e502a6b68876f5037b91972c4f72dac2e4e9b84f80f4b0790c2","sha256:d8d396eadc9a4f516284b8be48b1283f025d392c19e84c1c00e1187fe70bba53","sha256:27f473333e2f615c75d1350e314ad8641d9d13ad9f2dbb82999f2012c86a0c53","sha256:ae2a14e88adb05e51056b3ceaba6af7dccee9a987af4f2bae6243b51ba66a018","sha256:fd2315f0cf242aa3776d71f69fbe78d4088999ef9fc2df1de5cb513606be1215","sha256:eda01226259d5df53a10c6b6d7d760bfc37317a8037b98f17f23835fa26fc087"]},"Metadata": {"LastTagTime": "2025-04-13T16:23:58.435252063+08:00"}}
]
返回的是一个 JSON 格式的消息,如果我们只要其中一项内容时, 可以使用参数 -f 来指
定。
3.1.4 镜像导出 save、导入load
- 镜像导出:将本地仓库中的镜像文件导出到宿主机中
docker image save 镜像名称[:TAG] -o 目标文件[:TAG][.tar.gz]
或者
docker image save 镜像名称[:TAG] > 目标文件[:TAG][.tar.gz]
注意:-o 用于指定导出镜像的位置,可同时导出多个镜像为一个文件,指定 .tar.gz 可以导出并压缩。
# 例如,将nginx:1.27.4镜像导出到宿主机
[root@docker ~]# ls
anaconda-ks.cfg
[root@docker ~]# docker image save nginx:1.27.4 -o nginx.1.27.4.tag.gz
[root@docker ~]# ls
anaconda-ks.cfg nginx.1.27.4.tag.gz
- 镜像导入
docker [image] load -i 宿主机文件路径(-i:input)
# 例如,从宿主机中的/root/nginx1.27.4.tar.gz导入到docker中
docker rmi 镜像名:TAG/镜像ID #删除镜像
[root@docker ~]# docker rmi nginx:1.27.4
Untagged: nginx:1.27.4
Untagged: nginx@sha256:09369da6b10306312cd908661320086bf87fbae1b6b0c49a1f50ba531fef2eab
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
my-nginx 1.27.4 4cad75abc83d 2 months ago 192MB
mysql 8.4.4 4a8a163431d3 2 months ago 769MB
busybox latest ff7a7936e930 6 months ago 4.28MB[root@docker ~]# docker load -i /root/nginx.1.27.4.tag.gz
Loaded image: nginx:1.27.4
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
my-nginx 1.27.4 4cad75abc83d 2 months ago 192MB
nginx 1.27.4 4cad75abc83d 2 months ago 192MB
mysql 8.4.4 4a8a163431d3 2 months ago 769MB
busybox latest ff7a7936e930 6 months ago 4.28MB
3.1.5 拉取镜像 docker pull
docker pull NAME[:TAG]
不指定则为docker官方地址
[root@docker ~]# docker pull busybox
Using default tag: latest
latest: Pulling from library/busybox
97e70d161e81: Pull complete
Digest: sha256:37f7b378a29ceb4c551b1b5582e27747b855bbfaa73fa11914fe0df028dc581f
Status: Downloaded newer image for busybox:latest
docker.io/library/busybox:latest# 查看镜像列表
[root@docker ~]# docker images
仓库名称 标签
REPOSITORY TAG IMAGE ID CREATED SIZE
busybox latest ff7a7936e930 6 months ago 4.28MB
[root@docker ~]# docker pull nginx:1.27.4
1.27.4: Pulling from library/nginx
8a628cdd7ccc: Already exists
75b642592991: Already exists
553c8756fd66: Already exists
10fe6d2248e3: Pull complete
3b6e18ae4ce6: Pull complete
3dce86e3b082: Pull complete
e81a6b82cf64: Pull complete
Digest: sha256:09369da6b10306312cd908661320086bf87fbae1b6b0c49a1f50ba531fef2eab
Status: Downloaded newer image for nginx:1.27.4
docker.io/library/nginx:1.27.4
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx 1.27.4 4cad75abc83d 2 months ago 192MB
busybox latest ff7a7936e930 6 months ago 4.28MB[root@docker ~]# docker run --name nginx -d -p 80:80 nginx:1.27.4
6c8af7f90280fc04819e1661b7d98db8745d4dccaed97bf6aa6122a32f7c6e69
- msyql
[root@docker ~]# docker pull mysql:8.4.4
8.4.4: Pulling from library/mysql
cea172a6e83b: Pull complete
9f0eb82d78dc: Pull complete
30667541f13f: Pull complete
f5fefeb7f3b5: Pull complete
2e7405f0a17c: Pull complete
b7cefcf2c641: Pull complete
38945ff9f35a: Pull complete
3bcd4b133d74: Pull complete
f4511c9955c0: Pull complete
014654182aa2: Pull complete
Digest: sha256:23818b7d7de427096ab1427b2e3d9d5e14a5b933f9a4431a482d6414bc879091
Status: Downloaded newer image for mysql:8.4.4
docker.io/library/mysql:8.4.4
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx 1.27.4 4cad75abc83d 2 months ago 192MB
mysql 8.4.4 4a8a163431d3 2 months ago 769MB
busybox latest ff7a7936e930 6 months ago 4.28MB
3.1.6 删除本地镜像 docker [image] rmi
docker [image] rmi NAME[:TAG]
i:image
rm:删除
当同一个镜像拥有多个标签的时候,docker rmi命令只是删除该镜像多个标签中的指定标签而已,并不影响镜像文件。
当镜像只剩下一个标签的时候,使用docker rmi命令会彻底删除镜像
- 使用镜像ID删除镜像
docker rmi IMAGE ID
3.1.7 悬空镜像、删除悬空镜像
在 Docker 中,悬虚镜像( Dangling Images )是指那些没有 标签 且没有被任何容器使用的镜像。这些镜像通常是由于构建过程中生成的中间层镜像或未正确清理的镜像残留。删除悬虚镜像可以释放磁盘空间并保持 Docker 环境的整洁。
- 列出悬空镜像
#无悬空镜像
[root@docker ~]# docker images -f "dangling=true"
REPOSITORY TAG IMAGE ID CREATED SIZE
- 删除悬空镜像
使用 docker image prune 命令来删除删除悬虚镜像
[root@docker ~]# docker image prune -f
Total reclaimed space: 0B
3.1.8 上传镜像 docker push
docker push NAME[:TAG]
3.2 容器管理
创建 容器:docker create --name 容器名称 -d 镜像名称:标签
启动 容器:docker start 容器名称 | 容器ID
查看容器:docker ps [-a]
停止容器:docker stop 容器名称|容器ID
暂停容器:docker pause 容器名称|容器ID
创建并启动容器:docker run --name 容器名称 -d 镜像名称:标签
(-d:后台运行)进入容器:docker exec -it 容器名称 命令、docker attach 容器名称
将文件复制到容器中:docker cp 本地文件路径 容器路径
删除容器:docker rm [-f]
查看容器详细信息:docker inspect 容器名称|容器ID
查看容器操作日志 docker logs 容器名称|容器ID
3.2.1 创建与启动容器 create、start、run
创建容器:
docker create NAME[:TAG]
- 可以加选项参数
- -i:交互模式
- -t:伪终端
- -d:后台运行
- -rm:容器退出后是否自动删除
[root@docker ~]# docker create -it nginx:1.27.4
7317e0daf6c6015516127640abeca9725f2c7e7e411b2e95cfef0f4306f918d1
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@docker ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7317e0daf6c6 nginx:1.27.4 "/docker-entrypoint.…" 37 seconds ago Created modest_poincare
[root@docker ~]# docker start 7317
7317
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7317e0daf6c6 nginx:1.27.4 "/docker-entrypoint.…" About a minute ago Up 6 seconds 80/tcp modest_poincare
[root@docker ~]# curl 192.168.98.149
curl: (7) Failed to connect to 192.168.98.149 port 80: Connection refused
[root@docker ~]# docker stop 7317
7317
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
启动容器:
docker start [OPTIONS] CONTAINER [CONTAINER…]
新建并启动容器
docker run [OPTIONS] IMAGE [COMMAND] [ARG…]
- 常用选项如下:
-t:打开一个终端
-i:交互式运行
-d:后台运行
-p:端口映射,格式为:<hostport>:<container port>
–name:指定容器名称
–rm:容器一旦停止就会自动删除容器
–network:指定容器使用的网络
3.2.2 查看所有容器 docker ps
docker ps [OPTION]
#查看运行的容器
[root@localhost~]# docker ps
#查看所有容器
[root@localhost~]# docker ps -a
3.2.3 终止运行容器 stop 、kill
docker stop 容器ID -t 时间 (默认10秒)
docker kill 容器ID
处于终止状态的容器,可以通过 docker start 命令来重新启动docker restart 命令会将一个运行态的容器先终止,然后再重新启动。如果要停止所有容器,可以先查看容器编号,然后批量停止。
3.2.4 进入容器内部 docker exec
docker exec -it [容器ID] /bin/bash
execution:执行
[root@docker ~]# docker exec -it nginx /bin/bash
root@c9bc55b21a16:/# ls
bin dev docker-entrypoint.sh home lib64 mnt proc run srv tmp var
boot docker-entrypoint.d etc lib media opt root sbin sys usr
root@c9bc55b21a16:/# cd /
root@c9bc55b21a16:/# ls
bin dev docker-entrypoint.sh home lib64 mnt proc run srv tmp var
boot docker-entrypoint.d etc lib media opt root sbin sys usr
root@c9bc55b21a16:/# cd usr/
root@c9bc55b21a16:/usr# ls
bin games include lib lib64 libexec local sbin share src
root@c9bc55b21a16:/usr# cd share/
root@c9bc55b21a16:/usr/share# ls
X11 debconf fonts libgcrypt20 nginx terminfo
base-files debianutils gcc lintian pam util-linux
base-passwd dict gdb locale pam-configs xml
bash-completion doc info man perl5 zoneinfo
bug doc-base java maven-repo pixmaps zsh
ca-certificates dpkg keyrings menu polkit-1
common-licenses fontconfig libc-bin misc tabset
root@c9bc55b21a16:/usr/share# cd nginx/
root@c9bc55b21a16:/usr/share/nginx# ls
html
root@c9bc55b21a16:/usr/share/nginx# cd html/
root@c9bc55b21a16:/usr/share/nginx/html# ls
50x.html index.html
root@c9bc55b21a16:/usr/share/nginx/html# vim index2.html
bash: vim: command not found
root@c9bc55b21a16:/usr/share/nginx/html# vi index2.html
bash: vi: command not found
root@c9bc55b21a16:/usr/share/nginx/html# dnf install vim -y
bash: dnf: command not found
root@c9bc55b21a16:/usr/share/nginx/html# yum install vim -y
bash: yum: command not found
root@c9bc55b21a16:/usr/share/nginx/html# echo "index3"
index3
root@c9bc55b21a16:/usr/share/nginx/html# echo "index2" > index2.html
root@c9bc55b21a16:/usr/share/nginx/html# ls
50x.html index.html index2.html
root@c9bc55b21a16:/usr/share/nginx/html# exit
exit
3.2.5 查看容器信息 inspect、stats
docker inspect [容器ID]
docker stats [容器ID]
docker inspect [容器ID]
docker stats [容器ID]
docker logs 容器名[root@docker ~]# docker inspect nginx
[root@docker ~]# docker stats nginx
3.2.6 查看容器日志 docker logs
docker logs 容器名
[root@docker ~]# docker logs nginx
3.2.7 容器文件传输 docker cp
docker cp [容器名:文件路径] [宿主机路径]
# 将容器中的test.txt文件复制到宿主机/opt目录下
[root@localhost ~]# docker cp nginx:/test.txt /opt
Successfully copied 1.54kB to /opt
# 把本机文件复制到容器中
[root@localhost ~]# docker cp /etc/fstab nginx:/fstab
[root@docker ~]# echo index3.html > index3.html
[root@docker ~]# ls
anaconda-ks.cfg index3.html nginx.1.27.4.tag.gz[root@docker ~]# docker cp ./index3.html nginx:/usr/share/nginx/html/
Successfully copied 2.05kB to nginx:/usr/share/nginx/html/
[root@docker ~]# curl localhost/index3.html
index3.html[root@docker ~]# docker cp nginx:/usr/share/nginx/html/index2.html .
Successfully copied 2.05kB to /root/.
[root@docker ~]# ls
anaconda-ks.cfg index2.html index3.html nginx.1.27.4.tag.gz
3.2.8 删除容器 docker rm
docker rm [容器ID]
# 删除指定容器
[root@localhost~]# docker rm 243c32535da7
# 删除所有容器
[root@localhost~]# docker rm -f $(docker ps -qa)docker rm 命令只能删除处于终止或退出状态的容器,并不能删除还处于运行状态的容器。要直接删除一个运行中的容器,可以添加 -f 参数。Docker 会先 发送 SIGKILL 信给容器终止其中的应用,之后强行删除。
3.3 仓库管理
Docker Hub 是最大的公共镜像仓库(https://hub.docker.com/)。在公共仓库中注册一个账号,每 ID 可以免费拥有 1 个私有镜像。
3.3.1 登录仓库 docker login
docker login -u username -p password
默认登陆的是docker hub
[root@localhost ~]# docker login -u haha -p 123465
WARNING! Using --password via the CLI is insecure. Use --passwordstdin.
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/#credential
s-store
Login Succeeded
登录成功的用户可以上传个人制造的镜像。
3.3.2 登出仓库 docker logout
docker logout
可以同时登陆多个docker仓库,因此此命令一般不执行。
[root@localhost ~]# docker logout
Removing login credentials for https://index.docker.io/v1/
3.3.3 认证文件
Mac/Win 机器上的是隐藏密码的,但是在 Linux 下是显示密码的,只不过进行了 base64 编码,只要拷贝此文件到其他机器指定目录下(/root/.docker/config.json)即可免登录。
{"auths": {"https://index.docker.io/v1/": {"auth": "Z2F2aW5saTgwczpsanAxMjM0NjU="}},"HttpHeaders": {"User-Agent": "Docker-Client/19.03.12 (linux)"}
}
3.4 命令图谱
3.5 部署示例
[root@Docker-kd ~]# docker pull mysql:8.4.4
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
[root@Docker-kd ~]# systemctl status docker
○ docker.service - Docker Application Container EngineLoaded: loaded (/usr/lib/systemd/system/docker.service; disabled; preset: di>Active: inactive (dead)
TriggeredBy: ○ docker.socketDocs: https://docs.docker.com
[root@Docker-kd ~]# systemctl start docker
[root@Docker-kd ~]# docker pull mysql:8.4.4
Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
[root@docker ~]# vim /etc/docker/daemon.json
[root@docker ~]# cat /etc/docker/daemon.json
{"registry-mirrors": ["https://docker.1ms.run","https://func.ink","https://proxy.1panel.live","https://docker-0.unsee.tech","https://docker.zhai.cm","https://a.ussh.net","https://docker.1ms.run","https://docker.melikeme.cn","https://lispy.org","https://docker.hlmirror.com","https://docker.1panel.live","https://docker.xiaogenban1993.com","https://docker.1panel.top","https://docker.kejilion.pro","https://dockerpull.cn","https://docker.xuanyuan.me","https://docker.anye.in","https://hub.fast360.xyz"]
}
[root@docker ~]# systemctl daemon-reload
[root@docker ~]# systemctl restart docker
3.5.1 拉取 redis7.4.2 镜像
1)去 DockerHub 搜索 Redis 镜像
2)查看 Redis 镜像的名称和版本
3)利用 docker pull 命令拉取镜像
4)利用 docker save命令将 redis:latest 打包为一个 redis.tar.gz 包
5)利用 docker rmi 删除本地的 redis:latest
6)利用 docker load 重新加载 redis.tar.gz文件[root@docker ~]# docker pull redis:7.4.2
7.4.2: Pulling from library/redis
8a628cdd7ccc: Already exists
3ff860482ac5: Pull complete
811af041d785: Pull complete
a7e27cf18de4: Pull complete
8ae1ad8ce35e: Pull complete
759939a29cb5: Pull complete
4f4fb700ef54: Pull complete
cbb99c664e48: Pull complete
Digest: sha256:fbdbaea47b9ae4ecc2082ecdb4e1cea81e32176ffb1dcf643d422ad07427e5d9
Status: Downloaded newer image for redis:7.4.2
docker.io/library/redis:7.4.2
[root@docker ~]# docker save redis:7.4.2 -o redis:7.4.2.tar.gz
[root@docker ~]# ls
anaconda-ks.cfg index2.html index3.html nginx.1.27.4.tag.gz redis:7.4.2.tar.gz
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
my-nginx 1.27.4 4cad75abc83d 2 months ago 192MB
nginx 1.27.4 4cad75abc83d 2 months ago 192MB
mysql 8.4.4 4a8a163431d3 2 months ago 769MB
redis 7.4.2 65750d044ac8 3 months ago 117MB
busybox latest ff7a7936e930 6 months ago 4.28MB
[root@docker ~]# docker rmi 6575
Untagged: redis:7.4.2
Untagged: redis@sha256:fbdbaea47b9ae4ecc2082ecdb4e1cea81e32176ffb1dcf643d422ad07427e5d9
Deleted: sha256:65750d044ac86b73a473c01a854d5f7f2b55a77b43f007d0e10a5db5dd1d926f
Deleted: sha256:49cd550fc30bccf84f1f236a79253f001a3a9f3a1b02f0cc740f1398d76b8533
Deleted: sha256:e0690ddc013eedc562d913a51bc89341d373a52ad53470ecf6ecb8f0b1b5ffb5
Deleted: sha256:cb189b5d5dd0ce60f0025de7c92b8896a5ee1f6ac6f90d373ef478c74049ecef
Deleted: sha256:9085c007f78efd29de83469622ccd6f977bc9acafdf6998f5f7b9dffd95f9bba
Deleted: sha256:37036292b6f5df827b4c76531dad2cf87031eabeffa12bd353c91d66d18cf917
Deleted: sha256:52aab82e9b8bbc9277f4c34a7c4fdf4bcc50a612cd0483dffddbad5b5cab5b4d
Deleted: sha256:7de9d31c8a5b5a2f3ea465f8944b69877612aa0f52c32bc08e7be014ce58d441
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
my-nginx 1.27.4 4cad75abc83d 2 months ago 192MB
nginx 1.27.4 4cad75abc83d 2 months ago 192MB
mysql 8.4.4 4a8a163431d3 2 months ago 769MB
busybox latest ff7a7936e930 6 months ago 4.28MB
[root@docker ~]# docker load -i ./redis\:7.4.2.tar.gz
1910dfbcb631: Loading layer 10.75kB/10.75kB
aaf201c773fb: Loading layer 10.75kB/10.75kB
98ad392b916a: Loading layer 4.144MB/4.144MB
6108f9e7c02c: Loading layer 38.12MB/38.12MB
319c2310f2be: Loading layer 1.536kB/1.536kB
5f70bf18a086: Loading layer 1.024kB/1.024kB
570897943907: Loading layer 4.096kB/4.096kB
Loaded image: redis:7.4.2
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
my-nginx 1.27.4 4cad75abc83d 2 months ago 192MB
nginx 1.27.4 4cad75abc83d 2 months ago 192MB
mysql 8.4.4 4a8a163431d3 2 months ago 769MB
redis 7.4.2 65750d044ac8 3 months ago 117MB
busybox latest ff7a7936e930 6 months ago 4.28MB
[root@docker ~]# docker run -d --name redis -p 6379:6379 redis:7.4.2
3a992261f5b2d9599385929162488bd39a621c8bd67a561a0a8334fa5c26009f
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3a992261f5b2 redis:7.4.2 "docker-entrypoint.s…" 29 seconds ago Up 29 seconds 0.0.0.0:6379->6379/tcp, [::]:6379->6379/tcp redis
c9bc55b21a16 nginx:1.27.4 "/docker-entrypoint.…" 5 days ago Up About an hour 0.0.0.0:80->80/tcp, [::]:80->80/tcp nginx
[root@docker ~]# docker exec -it redis /bin/bash
root@3a992261f5b2:/data# redis-cli
127.0.0.1:6379> keys * #拿到所有键
(empty array)
127.0.0.1:6379> set name lisi
OK
127.0.0.1:6379> get name
"lisi"
127.0.0.1:6379> exit
root@3a992261f5b2:/data# exit
exit
3.5.2 安装MySQL
- 拉取或下载镜像
docker pull mysql:8.4.4 - 启动并运行MySQL容器
- 远程连接数据库
- 拉取镜像
[root@Docker-kd ~]# docker pull mysql:8.4.4
8.4.4: Pulling from library/mysql
cea172a6e83b: Pull complete
9f0eb82d78dc: Pull complete
30667541f13f: Pull complete
f5fefeb7f3b5: Pull complete
2e7405f0a17c: Pull complete
b7cefcf2c641: Pull complete
38945ff9f35a: Pull complete
3bcd4b133d74: Pull complete
f4511c9955c0: Pull complete
014654182aa2: Pull complete
Digest: sha256:23818b7d7de427096ab1427b2e3d9d5e14a5b933f9a4431a482d6414bc879091
Status: Downloaded newer image for mysql:8.4.4
docker.io/library/mysql:8.4.4
- 启动MySQL容器
[root@Docker-kd ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql 8.4.4 4a8a163431d3 3 months ago 769MB
[root@Docker-kd ~]# docker run -d \
--restart=always \ #数据库设为开机启动
--name mysql \ #指定容器的名称
-e MYSQL_ROOT_PASSWORD=123456 \ #环境变量
-p 3306:3306 \
--privileged=true \ #container内的root拥有真正的root权限
mysql:8.4.4 \ #指定镜像名称,并后台运行
--character-set-server=utf8mb4 \ #指定数据库的编码格式
--collation-server=utf8mb4_unicode_ci #指定数据库校对编码格式
2a92d462cc4f4bbf8c2e6ae68c9b2cd7c44b19c970bb2a073a9a8c97a976a944
- 远程连接数据库
# 执行如下命令进入到容器内部:
[root@Docker-kd ~]# docker exec -it mysql bash
bash-5.1# mysql -uroot -p123456
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.4.4 MySQL Community Server - GPLCopyright (c) 2000, 2025, Oracle and/or its affiliates.Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)mysql> exit
Bye
bash-5.1# exit
exit
3.5.3 安装Tomcat
- 拉取或下载镜像
- 启动并运行Tomcat容器
- 远程访问
[root@Docker-kd ~]# docker pull tomcat:11.0.5
11.0.5: Pulling from library/tomcat
2726e237d1a3: Pull complete
3a83fda68147: Pull complete
e18be1fe9d89: Pull complete
1080edf8b8b2: Pull complete
e17ac0079371: Pull complete
10681c58d83f: Pull complete
4f4fb700ef54: Pull complete
425b1a940d26: Pull complete
Digest: sha256:290c5145985129c59defd652cc091351260521498a057ae4f98d2113cf4844cb
Status: Downloaded newer image for tomcat:11.0.5
docker.io/library/tomcat:11.0.5[root@Docker-kd ~]# docker run -d \
> --restart=always \
> --name tomcat \
> -p 8080:8080 \
> tomcat:11.0.5
9a73207c3beb99519a62a831f735545866214e7d719a71d636ce66575e6b7b0e
打开浏览器,访问 http://localhost:8080 ,看到 Tomcat 的默认页面,表明 Tomcat 正在运行
四、Dicker 核心原理
- Docker Engine是具有以下主要组件的客户端-服务器应用程序:
- 服务器是一种长期运行的程序,称为守护程序进程( dockerd命令)。
- REST API,它指定程序可以用来与守护程序进行通信并指示其操作的接口。
- 命令行界面(CLI) 客户端(docker命令)。
这么做的好处就是可以通过 RestAPI 将客户端和服务段解耦,这样服务端就可以做到 Volume/Network 等做成插件化组装。
4.1 容器生命周期
- 状态与命令对应表
状态 | 说明 | 命令 |
---|---|---|
created | 初创建 | docker create |
running | 运行状态 | docker run、 docker start、docker restart、 docker uppause |
stopped | 停止状态 | docker stop、docker kill |
paused | 暂停状态 | docker pause |
deleted | 删除状态 | docker rm |
生命周期不可逆
- 状态转换图
需要根据实际情况选择的操作: - killed by out-of-memory(因内存不足被终止)
- 宿主机内存被耗尽,也被称为OOM:非计划终止,这时需要杀死最吃内存的容器,然后进行选择操作
- container process exitde(异常终止)
- 出现容器被终止后,将进入Should restart ? 选择操作:
- yes 需要重启,容器执行start命令,转为运行状态。
- no 不需要重启,容器转为停止状态。
4.2 容器命名空间
通过命名空间将进程之间隔离
4.2.1 进程命名空间(PID namespace)
PID namespace 对集成 PID 重新编号,即两个不同的 namespace下的进程可以用相同的 PID
[root@docker ~]# docker run --rm -d --network host nginx:1.27.4
caca07ee42cebb30569fd6e21ec623b5264f89b00df8aeef3d57595d205da552
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
caca07ee42ce nginx:1.27.4 "/docker-entrypoint.…" 5 seconds ago Up 4 seconds suspicious_hamilton
3a992261f5b2 redis:7.4.2 "docker-entrypoint.s…" 30 minutes ago Up 30 minutes 0.0.0.0:6379->6379/tcp, [::]:6379->6379/tcp redis
[root@docker ~]# ps -ef | grep docker
root 1134 1 0 18:52 ? 00:00:03 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
root 2540 1134 0 20:00 ? 00:00:00 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 6379 -container-ip 172.17.0.3 -container-port 6379 -use-listen-fd
root 2546 1134 0 20:00 ? 00:00:00 /usr/bin/docker-proxy -proto tcp -host-ip :: -host-port 6379 -container-ip 172.17.0.3 -container-port 6379 -use-listen-fd
root 3367 2078 0 20:31 pts/1 00:00:00 grep --color=auto docker
4.2.2 网络命名空间(network namespace)
通过网络命名空间,可以实现网络隔离
Docker采用虚拟网络设备(Virtual Network Device)的方式,将不同命名空间的网络设备连接到一起
默认情况下,容器中的虚拟网卡将同本地主机上的 docker0 网桥连接在一起。
4.2.3 IPC命名空间(IPC namespace)
进程间通信(Inter-Process Communitication, IPC)涉及的IPC资源包括常见的信号量,消息队列和共享内存。
申请 IPC 资源就申请了一个全局唯一的 32位 ID ,所以 IPC namespace中实际上包含了 系统IPC标识符 以及 实现POSIX消息队列的文件系统 。
PID Namespace 和 IPC Namespace 可以组合起来一起使用,在同一个IPC namespace下的进程彼此可见,不同IPC namespace下的进程则互相不可见。
4.2.4 挂载命名空间(Mount namespace)
类似于chroot,将一个进程放到一个特定的目录执行
挂载命名空间允许不同命名空间的进程看到的文件结构不同,这样每个命名空间中的进程所看到的文件目录彼此被隔离。
Mount namespace 通过隔离文件系统挂载点对隔离文件系统通过提供支持,是 Linux 支持的第一个 namespace 。
隔离后不同 mount namespace 中的文件结构发生变化也不互相影响,可以通过 /proc/[pid]/mounts 查看到所有挂载在当前 namespace 中的文件系统,还可以通过/proc/[pid]/mountstats 查到 mount namespace 中文件设备的统计信息,包括挂载文件的名字、文件系统、挂载位置等。
4.2.5 UTS命名空间(UTS namespace)
UTS(UNIX Time-sharing System)命名空间允许每个容器拥有独立的主机名和域名,从而可以虚拟出一个有独立主机名和网络空间的环境
就跟网络上一台独立的主机一样,每个 Docker 容器就可以拥有独立的主机名和容器了,在网络上可以被视作一个独立的节点,而非宿主机上的一个进程
默认情况下,Docker容器的主机名 就是 返回的容器 ID
Docker中,每个镜像基本上都以自身提供的服务名来命名镜像的 hostname,而且不会对宿主机产生任何影响,其原理就是利用了 UTS namespace
4.2.6 用户命名空间(User namespace)
每个容器可以有不同的用户和组id,也就是说可以在容器内使用特定的内部用户执行程序
,而非本地系统上存在的用户。
每个容器内部都可以有 root 帐号,但跟宿主主机不在一个命名空间。 通过使用隔离的用户命名空间可以提高安全性,避免容器内进程获取到额外的权限。
4.3 资源配额限制
控制组:对共享资源进行隔离、限制、审计(将所有操作记录下来,后续可通过这些记录判断是否合理)。只有能控制分配到容器的资源,才能避免多个容器同时竞争
控制组可以提供对容器的内存、CPU、磁盘IO等资源进行限制和管理。
默认情况下,容器没有资源限制
4.3.1 CPU
4.3.2 内存
大部分的选项取正整数,跟着一个后缀 b, k, m, g 表示字节,千字节,兆字节或千兆字节
[root@Docker-kd ~]# docker run --rm -d --network host -m 100m mysql:8.4.4
178a032756b77673afa98123b4e4aca2347cd7ee83ea86c9e6634403b0e36a3a
4.3.3 磁盘读写
Block I0指的是磁盘的读写,docker 可通过设置权重、限制bps和iops 的方式控制容器读写磁盘的带宽
[root@Docker-kd ~]# docker run -it --device-write-bps /dev/sra:30MB mysql:8.4.4
- 总结如下表:
4.4 联合文件系统
联合文件系统(UnionFS)是一种轻量级的高性能分层
文件系统,它支持将文件系统中的修改信息作为一次提交,并层层叠加,同时可以将不同目录挂载到同一个虚拟文件系统下,应用看到的是挂载的最终结果
UnionFS 可以把文件系统上多个目录(也叫分支)内容联合挂载到同一个目录下,而目录的物理位置是分开的联合文件系统是实现 Docker 镜像的技术基础。Docker 镜像可以通过分层来进行继承
4.4.1 Docker存储
当 Docker 利用镜像启动一个容器 时,将在镜像文件系统的 最顶端再挂载一个新的可读写的层给容器 。
容器中的内容更新将会发生在 可读写层
4.4.2 多种文件系统比较
Docker 目前支持的联合文件系统种类包括 AUFS、OverlayFS、 btrfs、vfs、zfs 和Device Mapper 等
4.5 容器网格管理
Docker 的 本地网络实现 其实就是利用了Linux上的网络命名空间和虚拟网络设备
要实现网络通信,机器需要至少一个网络接口(物理接口或虚拟接口)与外界相通,并可以收发数据包
如果 不同子网之间 要进行通信,需要
额外的路由机制
Docker 中的 网络接口 默认都是 虚拟的接口
[root@Docker-kd ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
de6743efaeb0 bridge bridge local
d248c162681d host host local
6a4fc2f818cf none null local
Docker容器网络在 本地主机 和 容器 内分别创建一个虚拟接口,并让它们彼此连通(这样的一对接口叫做veth pair)
- Docker的网络定义:
- bridge:默认值,在Docker网桥docker0上为容器创建新的网络栈。
- host:对于独立容器,不要将容器网络放到隔离的命名空间中,然后直接使用宿主机的网络(宿主机IP)。host 仅可用于Docker 17.06及更高版本上的集群服务
- overlay:覆盖网络将多个Docker守护程序连接在一起,并使群集服务能够相互通信。还可以使用覆盖网络来促进群集服务和独立容器之间或不同Docker守护程序上的两个独立容器之间的通信。这种策略消除了在这些容器之间进行操作系统级路由的需要
- macvlan:Macvlan网络允许将MAC地址分配给容器,使其在网络上显示为物理设备。Docker守护程序通过其MAC地址将流量路由到容器。macvlan 在处理希望直接连接到物理网络而不是通过Docker主机的网络堆栈进行路由的旧应用程序时,使用驱动程序有时是最佳选择
- none:对于此容器,禁用所有联网。通常与自定义网络驱动程序
(user_defined_network)一起使用。 - 网络插件:可以在Docker上安装和使用第三方网络插件。
4.5.1 Bridge 网络模式
当Docker进程启动时,会在主机上创建一个名为
docker0
的虚拟网桥,此主机上启动的 Docker 容器会连接到这个虚拟网桥上,所以有默认地址172.17.0.0/16的地址。虚拟网桥的工作方式和物理交换机类似,这样 主机上的所有容器就通过交换机连在了一个二层网络中
bridge 模式是 docker 的默认网络模式,不写 --net 参数,就是 bridge 模式。使用 docker run -p 时,docker 实际是在 iptables 做了 DNAT 规则,实现端口转发功能。可以使用 iptables -t nat -vnL 查看
[root@Docker-kd ~]# docker run --name bx1 -it --network bridge --rm busybox:latest
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
97e70d161e81: Pull complete
Digest: sha256:37f7b378a29ceb4c551b1b5582e27747b855bbfaa73fa11914fe0df028dc581f
Status: Downloaded newer image for busybox:latest
/ # ifconfig
eth0 Link encap:Ethernet HWaddr EE:5B:96:84:2A:91inet addr:172.17.0.4 Bcast:172.17.255.255 Mask:255.255.0.0UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1RX packets:7 errors:0 dropped:0 overruns:0 frame:0TX packets:3 errors:0 dropped:0 overruns:0 carrier:0collisions:0 txqueuelen:0RX bytes:586 (586.0 B) TX bytes:126 (126.0 B)lo Link encap:Local Loopbackinet addr:127.0.0.1 Mask:255.0.0.0inet6 addr: ::1/128 Scope:HostUP LOOPBACK RUNNING MTU:65536 Metric:1RX packets:0 errors:0 dropped:0 overruns:0 frame:0TX packets:0 errors:0 dropped:0 overruns:0 carrier:0collisions:0 txqueuelen:1000RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)/ # route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 172.17.0.1 0.0.0.0 UG 0 0 0 eth0
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0
/ # ping 192.168.98.140 正常访问宿主机
PING 192.168.98.140 (192.168.98.140): 56 data bytes
64 bytes from 192.168.98.140: seq=0 ttl=64 time=0.095 ms
64 bytes from 192.168.98.140: seq=1 ttl=64 time=0.061 ms
^C
--- 192.168.98.140 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.061/0.078/0.095 ms
/ # exit
4.5.2 Host 网络模式
如果启动容器的时候使用 host 模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个 Network Namespace。
容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的
。
[root@Docker-kd ~]# ifconfig
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255inet6 fe80::1814:3dff:fe93:1dcb prefixlen 64 scopeid 0x20<link>ether 1a:14:3d:93:1d:cb txqueuelen 0 (Ethernet)RX packets 16 bytes 560 (560.0 B)RX errors 0 dropped 0 overruns 0 frame 0TX packets 10 bytes 916 (916.0 B)TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0ens160: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500inet 192.168.98.140 netmask 255.255.255.0 broadcast 192.168.98.255inet6 fe80::20c:29ff:fed1:51f1 prefixlen 64 scopeid 0x20<link>ether 00:0c:29:d1:51:f1 txqueuelen 1000 (Ethernet)RX packets 6149 bytes 2661719 (2.5 MiB)RX errors 0 dropped 0 overruns 0 frame 0TX packets 7858 bytes 918903 (897.3 KiB)TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536inet 127.0.0.1 netmask 255.0.0.0inet6 ::1 prefixlen 128 scopeid 0x10<host>loop txqueuelen 1000 (Local Loopback)RX packets 0 bytes 0 (0.0 B)RX errors 0 dropped 0 overruns 0 frame 0TX packets 0 bytes 0 (0.0 B)TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0veth7479eef: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500inet6 fe80::4ca0:45ff:fec2:d646 prefixlen 64 scopeid 0x20<link>ether 4e:a0:45:c2:d6:46 txqueuelen 0 (Ethernet)RX packets 3 bytes 126 (126.0 B)RX errors 0 dropped 0 overruns 0 frame 0TX packets 27 bytes 1910 (1.8 KiB)TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0vethc75e009: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500inet6 fe80::303b:7cff:fe11:f216 prefixlen 64 scopeid 0x20<link>ether 32:3b:7c:11:f2:16 txqueuelen 0 (Ethernet)RX packets 3 bytes 126 (126.0 B)RX errors 0 dropped 0 overruns 0 frame 0TX packets 29 bytes 2062 (2.0 KiB)TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0[root@Docker-kd ~]# docker run --name bx2 -it --network host busybox:latest
/ # ifconfig 和宿主机一样
docker0 Link encap:Ethernet HWaddr 1A:14:3D:93:1D:CBinet addr:172.17.0.1 Bcast:172.17.255.255 Mask:255.255.0.0inet6 addr: fe80::1814:3dff:fe93:1dcb/64 Scope:LinkUP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1RX packets:16 errors:0 dropped:0 overruns:0 frame:0TX packets:10 errors:0 dropped:0 overruns:0 carrier:0collisions:0 txqueuelen:0RX bytes:560 (560.0 B) TX bytes:916 (916.0 B)ens160 Link encap:Ethernet HWaddr 00:0C:29:D1:51:F1inet addr:192.168.98.140 Bcast:192.168.98.255 Mask:255.255.255.0inet6 addr: fe80::20c:29ff:fed1:51f1/64 Scope:LinkUP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1RX packets:6501 errors:0 dropped:0 overruns:0 frame:0TX packets:8469 errors:0 dropped:0 overruns:0 carrier:0collisions:0 txqueuelen:1000RX bytes:2687363 (2.5 MiB) TX bytes:990956 (967.7 KiB)lo Link encap:Local Loopbackinet addr:127.0.0.1 Mask:255.0.0.0inet6 addr: ::1/128 Scope:HostUP LOOPBACK RUNNING MTU:65536 Metric:1RX packets:0 errors:0 dropped:0 overruns:0 frame:0TX packets:0 errors:0 dropped:0 overruns:0 carrier:0collisions:0 txqueuelen:1000RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)veth7479eef Link encap:Ethernet HWaddr 4E:A0:45:C2:D6:46inet6 addr: fe80::4ca0:45ff:fec2:d646/64 Scope:LinkUP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1RX packets:3 errors:0 dropped:0 overruns:0 frame:0TX packets:27 errors:0 dropped:0 overruns:0 carrier:0collisions:0 txqueuelen:0RX bytes:126 (126.0 B) TX bytes:1910 (1.8 KiB)vethc75e009 Link encap:Ethernet HWaddr 32:3B:7C:11:F2:16inet6 addr: fe80::303b:7cff:fe11:f216/64 Scope:LinkUP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1RX packets:3 errors:0 dropped:0 overruns:0 frame:0TX packets:29 errors:0 dropped:0 overruns:0 carrier:0collisions:0 txqueuelen:0RX bytes:126 (126.0 B) TX bytes:2062 (2.0 KiB)/ #
4.5.3 Container 网络模式
这个模式指定 新创建的容器 和 已经存在的一个容器 共享一个 Network Namespace
,而不是和宿主机共享。
新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。
- 在一个终端,使用 bridge 网络模式启动容器 b1
[root@Docker-kd ~]# docker run --name b1 -it --rm busybox:latest / # ifconfig
eth0 Link encap:Ethernet HWaddr C6:4A:9E:DB:98:A7inet addr:172.17.0.4 Bcast:172.17.255.255 Mask:255.255.0.0UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1RX packets:10 errors:0 dropped:0 overruns:0 frame:0TX packets:3 errors:0 dropped:0 overruns:0 carrier:0collisions:0 txqueuelen:0RX bytes:796 (796.0 B) TX bytes:126 (126.0 B)lo Link encap:Local Loopbackinet addr:127.0.0.1 Mask:255.0.0.0inet6 addr: ::1/128 Scope:HostUP LOOPBACK RUNNING MTU:65536 Metric:1RX packets:0 errors:0 dropped:0 overruns:0 frame:0TX packets:0 errors:0 dropped:0 overruns:0 carrier:0collisions:0 txqueuelen:1000RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)/ # echo "hello world b1" > /tmp/index.html
/ # httpd -h /tmp/ #在b1上启动httpd服务
/ # netstat -nutl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 :::80 :::* LISTEN
/ #
- 在另一个终端使用 Container 网络模式创建容器 b2
[root@Docker-kd ~]# docker run --name b2 -it --network container:b1 --rm busybox:latest
/ # ifconfig b2的ip和b1一样
eth0 Link encap:Ethernet HWaddr C6:4A:9E:DB:98:A7inet addr:172.17.0.4 Bcast:172.17.255.255 Mask:255.255.0.0UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1RX packets:9 errors:0 dropped:0 overruns:0 frame:0TX packets:3 errors:0 dropped:0 overruns:0 carrier:0collisions:0 txqueuelen:0RX bytes:726 (726.0 B) TX bytes:126 (126.0 B)lo Link encap:Local Loopbackinet addr:127.0.0.1 Mask:255.0.0.0inet6 addr: ::1/128 Scope:HostUP LOOPBACK RUNNING MTU:65536 Metric:1RX packets:0 errors:0 dropped:0 overruns:0 frame:0TX packets:0 errors:0 dropped:0 overruns:0 carrier:0collisions:0 txqueuelen:1000RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)/ # wget -O - -q 127.0.0.1 #b1启动的httpd服务,在b2上直接访问
hello world b1
/ # ls /tmp/ #但是文件系统并不共享,只共享网络
/ #
4.5.4 None 网络模式
使用none模式,Docker容器拥有自己的Network Namespace,但是,并不为Docker 容器进行任何网络配置。
也就是说,这个 Docker 容器没有网卡、IP、路由等信息,
只有lo 网络接口
。需要自己为Docker容器添加网卡、配置IP等
不参与网络通信,运行于此类容器中的进程仅能访问本地回环接口;仅适用于进程无须网络通信的场景中,例如:备份、进程诊断及各种离线任务等
[root@Docker-kd ~]# docker run --name b3 -it --network none --rm busybox:latest
/ # ifconfig
lo Link encap:Local Loopbackinet addr:127.0.0.1 Mask:255.0.0.0inet6 addr: ::1/128 Scope:HostUP LOOPBACK RUNNING MTU:65536 Metric:1RX packets:0 errors:0 dropped:0 overruns:0 frame:0TX packets:0 errors:0 dropped:0 overruns:0 carrier:0collisions:0 txqueuelen:1000RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)/ # route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
/ # exit
[root@Docker-kd ~]#
4.5.5 Docker 外部访问容器
容器中可以运行一些网络应用,要让外部也可以访问这些应用,可以通过 -P 或 -p 参数来指定端口映射。当使用 -P 标记时,Docker 会随机映射一个 49000~49900 的端口到内部容器开放的网络端口
[root@Docker-kd ~]# docker run -d -P busybox:latest ls /# 使用 docker container ls 可以看到,本地主机的 49155 被映射到了容器的 5000 端口。
# 此时访问本机的 49155 端口即可访问容器内 web 应用提供的界面。
[root@Docker-kd ~]# docker container ls -l
CONTAINER ID IMAGE COMMAND CREATEDATUS PORTS NAMES
bc533791f3f5 training/webapp:latest python app.py 5 seconds ago Up 2 seconds 0.0.0.0:49155->5000/tcp nostalgic_morse
# 通过 docker logs 命令来查看应用的信息
[root@Docker-kd ~]# docker logs -f nostalgic_morse
* Running on http://0.0.0.0:5000/
10.0.2.2 - - [23/May/2014 20:16:31] "GET / HTTP/1.1" 200 -
10.0.2.2 - - [23/May/2014 20:16:31] "GET /favicon.ico HTTP/1.1" 404 -# -p 则可以指定要映射的端口,并且,在一个指定端口上只可以绑定一个容器。
# 支持的格式有 ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort
4.5.5.1 映射所有端口地址
使用 hostPort:containerPort
格式本地的 5000 端口映射到容器的 5000 端口,可以执行
[root@Docker-kd ~]# docker run -d -p 5000:5000 training/webapp python app.py
此时默认会 绑定本地所有接口上的所有地址
4.5.5.2 映射到指定地址的指定端口
可以使用 ip:hostPort:containerPort
格式指定映射使用一个特定地址,比如 localhost 地址 127.0.0.1
[root@Docker-kd ~]# docker run -d -p 127.0.0.1:5000:5000 training/webapp python app.py
4.5.5.3 映射到指定地址的任意端口
使用 ip::containerPort
绑定 localhost 的任意端口到容器的 5000 端口,本地主机会自动分配一个端口
[root@Docker-kd ~]# docker run -d -p 127.0.0.1::5000 training/webapp python app.py
还可以使用 udp 标记来指定 udp 端口
[root@Docker-kd ~]# docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py
4.5.5.4 查看映射端口配置
使用 docker port 来查看当前映射的端口配置,也可以查看到绑定的地址
[root@Docker-kd ~]# docker port nostalgic_morse 5000 127.0.0.1:49155.
- 注意:
- 容器有自己的内部网络和 ip 地址(使用 docker inspect 可以获取所有的变量,Docker 还可以有一个可变的网络配置。)
- -p 标记可以多次使用来绑定多个端口
例如:
[root@Docker-kd ~]# docker run -d \
-p 5000:5000 \
-p 3000:80 \
training/webapp \
python app.py
4.5.6 Docker 容器互联
建议使用 自定义的网络 来控制哪些容器可以相互通信,还可以自动DNS解析容器名称到 IP地址
# docker network 通过 tab键,命令可选择以下选项
[root@docker ~]# docker network
connect (Connect a container to a network)
create (Create a network)
disconnect (Disconnect a container from a network)
inspect (Display detailed information on one or more networks)
ls (List networks)
prune (Remove all unused networks)
rm (Remove one or more networks)
- 新建网络
[root@docker ~]# docker network create -d bridge my-net
864299a0da6369d7178b759386069ed4d8d14fd84ac70f9999e449fc870dfc61
[root@docker ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
5309795a0986 bridge bridge local
a39999e255cc host host local
864299a0da63 my-net bridge local
33ff0068d12d none null local
[root@docker ~]# docker network create -d host my-net2
Error response from daemon: only one instance of "host" network is allowed
-d:指定网络类型,bridge 或者 overlay,overlay网络类型用于 Swarm mode
# 默认即为bridge
[root@docker ~]# docker network create my-net3
0d7c63288846fe3dda5daf7b5191227a615ed02308eb144d1a70bce444d4dbe3
[root@docker ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
5309795a0986 bridge bridge local
a39999e255cc host host local
864299a0da63 my-net bridge local
0d7c63288846 my-net3 bridge local
33ff0068d12d none null local
- 连接容器
# 运行一个容器并连接到新建的 my-net 网络
[root@docker ~]# docker run --name b1 --rm -it --network my-net busybox:latest
/ ## 打开新的终端,再运行一个容器并加入到 my-net 网络
[root@docker ~]# docker run --name b2 --rm -it --network my-net busybox:latest
# 通过 ping 来证明 b1 和 b2 容器建立了互联关系
/ # ping b11
PING b11 (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.076 ms
64 bytes from 172.18.0.3: seq=1 ttl=64 time=0.073 ms
^C64 bytes from 172.18.0.3: seq=4 ttl=64 time=0.128 ms
--- b1 ping statistics ---
7 packets transmitted, 7 packets received, 0% packet loss
round-trip min/avg/max = 0.073/0.105/0.156 ms
4.5.7 Docker 配置DNS
在容器中可通过 mount 命令查看挂载信息
[root@docker ~]# mount
/dev/disk/by-uuid/1fec...ebdf on /etc/hostname type ext4 ...
/dev/disk/by-uuid/1fec...ebdf on /etc/hosts type ext4 ...
tmpfs on /etc/resolv.conf type tmpfs ...
- 配置全部容器的 DNS ,也可以在 /etc/docker/daemon.json 文件中增加以下内容来设置
{"dns" : ["223.5.5.5","8.8.8.8"]
}
# 用以下命令来证明其已经生效
[root@docker ~]# docker run -it --rm ubuntu:22.04 cat /etc/resolv.conf
Unable to find image 'ubuntu:22.04' locally
22.04: Pulling from library/ubuntu
30a9c22ae099: Pull complete
Digest: sha256:d80997daaa3811b175119350d84305e1ec9129e1799bba0bd1e3120da3ff52c3
Status: Downloaded newer image for ubuntu:22.04
# Generated by Docker Engine.
# This file can be edited; Docker Engine will not make further changes once it
# has been modified.nameserver 223.5.5.5
nameserver 8.8.8.8
nameserver 223.6.6.6
search localdomain# Based on host file: '/etc/resolv.conf' (legacy)
# Overrides: [nameservers]
- 删除网络
docker network rm 网络名称[root@docker ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
34e892a71969 bridge bridge local
a39999e255cc host host local
864299a0da63 my-net bridge local
0d7c63288846 my-net3 bridge local
33ff0068d12d none null local
[root@docker ~]# docker network rm my-net3 my-net
my-net3
my-net
[root@docker ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
34e892a71969 bridge bridge local
a39999e255cc host host local
33ff0068d12d none null local
4.6 容器数据管理
[root@docker ~]# docker volume
create (Create a volume)
inspect (Display detailed information on one or more volumes)
ls (List volumes)
prune (Remove unused local volumes)
rm (Remove one or more volumes)
update (Update a volume (cluster volumes only))
- volume , bind 和 tmpfs 三者的相同点和区别:
- 相同之处:
- 无论选择使用哪种类型去使用,数据在容器内看起来都是相同的。它被视为容器文件系统中的目录或单个文件。
- 不同之处:
- 卷(volume)存储在由 Docker 管理的主机文件系统中/var/lib/docker/volumes/。非 Docker 进程不应该修改这部分文件系统。
卷是在Docker 中保留数据的最佳方式
。 - 绑定挂载(bind mount) 也就是把主机的本地目录挂载到容器中某个挂载点,可以存储在主机系统的任何位置。他们甚至可能是重要的系统文件或目录。Docker主机或Docker容器上的非Docker进程可以随时修改它们。
- tmpfs挂载(tmpfs mount)仅存储在主机系统的内存中,而不会写入主机系统的文件系统
- 卷(volume)存储在由 Docker 管理的主机文件系统中/var/lib/docker/volumes/。非 Docker 进程不应该修改这部分文件系统。
- 相同之处:
4.6.1 数据管理命令
- 数据卷操作
# 1.显式创建卷
docker volume create 数据卷名称# 2.在容器内创建卷
docker run -itd --name 容器名字 -v 宿主机文件:容器文件 镜像名称#注意
-v:宿主机文件:容器文件 可以存在多个,表示同时挂载多个
宿主机文件尽量用绝对路径,容器文件即使不存在,Docker 会自动创建
- 数据卷容器操作
# 1、创建数据卷容器
docker create -v [宿主机文件]:[容器数据卷目录] --name [容器名字] [镜像名称] [命令(可选)]# 2、使用数据卷容器
docker run --volumes-from [数据卷容器名字] -d --name [容器名字] [镜像名称] [命令(可选)]
4.6.2 数据卷实战
数据卷(Data Volumes)是由 Docker 创建和管理,是一个可供容器使用的特殊目录,它将主机操作系统目录直接映射进容器,类似于 Linux 中的 mount 操作
- 创建数据卷
# 创建一个名为 my-vol 的数据卷
[root@localhost ~]# docker volume create myvol# 查看数据卷
[root@localhost ~]# docker volume ls
local myvol# 查看详细信息
[root@localhost ~]# docker volume inspect myvol
[{"Driver": "local","Labels": {},"Mountpoint": "/var/lib/docker/volumes/myvol/_data","Name": "myvol","Options": {},"Scope": "local"}
]
- 使用数据卷
# 使用创建好的数据卷
[root@localhost ~]# docker run -tid --name web1 -p 80:80 -v
myvol:/usr/share/nginx/html nginx:1.27.4# 启动nginx容器并且挂载硬盘
[root@localhost ~]# docker run -itd --name web2 -p 80:80 -v
/tmp/test.txt:/test/file/test.sh nginx:1.27.4
- 删除数据卷
# 删除数据卷
[root@localhost ~]# docker volume rm myvol# 清理未使用的数据卷
[root@localhost ~]# docker volume prune
4.6.3 数据卷容器实战
数据卷容器(Data Volumes Containers)也成为绑定挂载,使用绑定安装时,主机上的文件或目录将安装到容器中,该文件或目录不需要在 Docker 主机上已经存在。如果尚不存在,则按需创建。
- 创建数据卷
# 创建宿主机的目录
[root@localhost ~]# mkdir /data# 创建voldata容器
[root@localhost ~]# docker create -v /data:/data --name voldata
nginx:1.27.4# 使用 docker inspect voldata 验证创建卷并安装正确。查找Mounts 部分:
[root@localhost ~]# docker inspect voldata
"Mounts": [{"Type": "volume","Name": "data","Source": "/var/lib/docker/volumes/data/_data","Destination": "/data","Driver": "local","Mode": "","RW": true,"Propagation": ""}
],# 这表明安装是一个卷,它显示了正确的源和目标,并且该安装是可读写的
- 挂载数据卷
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED
STATUS PORTS NAMES
1b1988626027 nginx:1.27.4 "/docker-entrypoint.…" 16 seconds ago
Created voldata# 挂载数据卷
[root@localhost ~]# docker run --volumes-from voldata -d --rm --name
vc-test1 nginx:1.27.4
[root@localhost ~]# docker run --volumes-from voldata -d --rm --name
vc-test2 nginx:1.27.4
# 进入vc-test1,操作数据卷容器
[root@localhost ~]# docker exec -it vc-test1 /bin/bash
root@c4da80319e8c:/# echo "vc-test1" > /data/vc-test1.txt
root@c4da80319e8c:/# exit# 进入vc-test2,确认数据卷
[root@localhost ~]# docker exec -it vc-test2 /bin/bash
root@5c5204337447:/# cat /data/vc-test1.txt
vc-test1
root@5c5204337447:/# echo "vc-test2" > /data/vc-test2.txt
root@5c5204337447:/# exit# 回到vc-test1进行验证
[root@localhost ~]# docker exec -it vc-test1 cat /data/vc-test2.txt
vc-test2# 回到宿主机查看/data/目录
[root@localhost ~]# ll /data/
-rw-r--r--. 1 root root 9 5月 17 23:40 vc-test1.txt
-rw-r--r--. 1 root root 9 5月 17 23:41 vc-test2.txt
- 使用只读绑定安装
# 1.启动容器
[root@localhost ~]# docker run -d \
-it \
--name devtest \
-v "$(pwd)"/target:/app:ro \
nginx:1.27.4# 2.使用 docker inspect devtest 验证绑定安装正确创建。查找 Mounts 部分:
[root@localhost ~]# docker inspect devtest
"Mounts": [{"Type": "bind","Source": "/root/target","Destination": "/app","Mode": "ro","RW": false,"Propagation": "rprivate"}
],
4.6.4 tmpfs 挂载
要在容器中使用 tmpfs ,使用 --tmpfs 标志,或将 --mount 标志与 type=tmpfs 和destination 选项一起使用。
- 在Nginx容器上创建一个tmpfs 安装/app
[root@localhost ~]# docker run -d \
-it \
--name tmptest \
--tmpfs /app \
nginx:1.27.4#tmpfs 通过运行 docker container inspect tmptest 并查找以下 Mounts 部分来验证安装是否为安装:
[root@localhost ~]# docker container inspect tmptest
"Tmpfs": {"/app": ""
},# 卸下容器
[root@localhost ~]# docker container stop tmptest
[root@localhost ~]# docker container rm tmptest
- 指定tmpfs选项
tmpfs 安装允许两个配置选项,都不是必需的。如果需要指定这些选项,则必须使用 --mount 标志,因为该 --tmpfs 标志不支持它们。
tmpfs-size : tmpfs 安装的大小(以字节为单位),默认情况下不受限制
# 以下示例将设置tmpfs-mode为1770
[root@localhost ~]# docker run -d \
-it \
--name tmptest \
--mount type=tmpfs,destination=/app,tmpfs-mode=1770 \
nginx:1.27.4
[root@docker ~]# docker run -d -it --name tmptest --tmpfs /app nginx:1.27.4
0fa3ccb0cdcac4bb4ef87bc1a0ba4de14af8335435eae52329e7a46449242e01
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0fa3ccb0cdca nginx:1.27.4 "/docker-entrypoint.…" 3 seconds ago Up 3 seconds 80/tcp tmptest
[root@docker ~]# docker container inspect tmptest
[{"Id": "0fa3ccb0cdcac4bb4ef87bc1a0ba4de14af8335435eae52329e7a46449242e01","Created": "2025-04-20T13:05:38.26061022Z","Path": "/docker-entrypoint.sh","Args": ["nginx","-g","daemon off;"],
.....................
# 删除
[root@docker ~]# docker container stop tmptest
tmptest
[root@docker ~]# docker rm tmptest
tmptest
4.6.5 数据卷备份还原
- 数据备份方案
- 创建一个挂载数据卷容器的容器
- 挂载宿主机本地目录作为备份数据卷
- 将数据卷容器的内容备份到宿主机本地目录挂载的数据卷中
- 完成备份操作后销毁刚创建的容器以及关联的容器卷
命令格式:
docker run --rm --volumes-from [数据卷容器id/name] -v [宿主机目录]:[容器目录] [镜像名称] [备份命令]
- 数据恢复方案
- 创建一个新的数据卷容器
- 创建一个新容器,挂载数据卷容器,同时挂载本地的备份目录作为数据卷
- 将要恢复的数据解压到容器中
- 完成还原操作后销毁刚创建的容器以及关联的容器卷
命令格式:
docker run --rm -itd --volumes-from [数据要到恢复的容器] -v [宿主机备份目录]:[容器备份目录] [镜像名称] [解压命令]
4.7 实战案例
- 备份实战
# 1.数据卷容器备份
#创建备份的目录
[root@localhost ~]# mkdir /backup
#创建备份的容器,并且挂载/backup,然后执行备份压缩至/data,/data 是数据容器卷中容器内数据目录
[root@localhost ~]# docker run --rm \
--volumes-from voldata \
-v /backup:/backup nginx:1.27.4 \
tar zcf /backup/data.tar.gz /data
#验证操作
[root@localhost ~]# ll /backup/
-rw-r--r--. 1 root root 181 5月 18 11:11 data.tar.gz
[root@localhost ~]# tar tf /backup/data.tar.gz
data/
data/vc-test1.txt
data/vc-test2.txt
注意:
解压的时候,如果使用目录的话,一定要在解压的时候使用 -C 制定挂载的数据卷容器,不然的话容器数据是无法恢复的,因为容器中默认的backup目录不是数据卷,即使解压后,也看不到文件。
# 2.数据卷备份
[root@localhost ~]# docker run -it -v /root/test:/dbdata --name nginx
nginx:1.27.4
[root@localhost ~]# docker run --volumes-from dbdata -v $(pwd):/backup
nginx:1.27.4 tar cvf /backup/backup.tar /dbdata
- 还原实战
# 1.删除vc-test1的数据
#删除vc-test1的数据
[root@localhost ~]# docker exec -it vc-test1 /bin/bash
root@bcd97d50b9f5:/# rm -fr /data/*# 2.还原数据
# 恢复数据
[root@localhost ~]# docker run --rm --volumes-from voldata -v
/backup:/backup nginx:1.27.4 tar xf /backup/data.tar.gz -C /# vc-test1容器查看
[root@localhost ~]# docker exec vc-test1 ls -l /data
total 8
-rw-r--r--. 1 root root 9 May 17 15:40 vc-test1.txt
-rw-r--r--. 1 root root 9 May 17 15:41 vc-test2.txt
- 安装MySQL
# 1.拉取或加载镜像
[root@localhost ~]# docker pull mysql:8.4.4
# 或者
[root@localhost ~]# docker load -i mysql:8.4.4.tar.gz# 2.创建挂载目录(在 /opt/ 下创建 mysql 数据卷目录)
[root@localhost ~]# mkdir -p /opt/mysql/{conf,data,logs}# 3.创建简单容器(创建并运行一个简单容器,便于拷贝容器中的配置文件)(此步可省略)
[root@localhost ~]# docker run --name mysql01 -e
MYSQL_ROOT_PASSWORD=123456 -d mysql:8.4.4# 4.拷贝配置文件(把容器中的配置文件和目录拷贝到宿主机挂载目录中)(此步可省略)
[root@localhost ~]# docker cp mysql01:/etc/my.cnf /opt/mysql/conf/
[root@localhost ~]# docker cp mysql01:/etc/mysql/conf.d
/opt/mysql/conf/# 5.停止容器
[root@localhost ~]# docker stop mysql01# 6.删除容器
[root@localhost ~]# docker rm mysql01# 7.安装MySQL
[root@localhost ~]# docker run -d \
--restart=always \
--name mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
-e MYSQL_USER=jock \
-e MYSQL_PASSWORD=123456 \
-p 3306:3306 \
-v /opt/mysql/conf/my.cnf:/etc/my.cnf \
-v /opt/mysql/conf:/etc/mysql/conf.d \
-v /opt/mysql/logs:/logs \
-v /opt/mysql/data:/var/lib/mysql \
--privileged=true \
mysql:8.4.4 \
--character-set-server=utf8mb4 \
--collation-server=utf8mb4_unicode_ci
[root@docker ~]# docker run --name mysql01 -e MYSQL_ROOT_PASSWORD=123456 -d mysql:8.4.4
24c1916a7f43874a0f758462073f9cbf8da042bf65c84a0d43108ac83a5256a4
[root@docker ~]# docker exec -it mysql01 /bin/bash
bash-5.1# pwd
/
bash-5.1# ls
afs dev home media proc sbin tmp
bin docker-entrypoint-initdb.d lib mnt root srv usr
boot etc lib64 opt run sys var
bash-5.1# cd var/
bash-5.1# ls
adm db ftp kerberos local log nis preserve spool yp
cache empty games lib lock mail opt run tmp
bash-5.1# cd log
bash-5.1# ls
mysqld.log
bash-5.1# cd ..
bash-5.1# ls
adm db ftp kerberos local log nis preserve spool yp
cache empty games lib lock mail opt run tmp
bash-5.1# cd lib
bash-5.1# ls
alternatives games mysql mysql-keyring rpm-state supportinfo
dnf misc mysql-files rpm selinux
bash-5.1# cd /
bash-5.1# ls
afs dev home media proc sbin tmp
bin docker-entrypoint-initdb.d lib mnt root srv usr
boot etc lib64 opt run sys var
bash-5.1# cd etc/
bash-5.1# ls
GREP_COLORS host.conf mysql rwtab.d
X11 hostname netconfig sasl2
aliases hosts networks selinux
alternatives inputrc nsswitch.conf services
bash_completion.d issue nsswitch.conf.bak shadow
bashrc issue.d openldap shadow-
bindresvport.blacklist issue.net opt shells
crypto-policies krb5.conf oracle-release skel
csh.cshrc krb5.conf.d os-release ssl
csh.login ld.so.cache passwd statetab.d
default ld.so.conf passwd- subgid
dnf ld.so.conf.d pkcs11 subuid
environment libaudit.conf pki swid
ethertypes libreport pm sysconfig
exports libssh popt.d system-release
filesystems localtime printcap system-release-cpe
gcrypt login.defs profile terminfo
gnupg logrotate.d profile.d xattr.conf
group motd protocols xdg
group- motd.d redhat-release yum.repos.d
gshadow mtab resolv.conf
gshadow- my.cnf rpc
gss my.cnf.d rpm
bash-5.1# cat my.cnf
# For advice on how to change settings please see
# http://dev.mysql.com/doc/refman/8.4/en/server-configuration-defaults.html[mysqld]
#
# Remove leading # and set to the amount of RAM for the most important data
# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
# innodb_buffer_pool_size = 128M
#
# Remove leading # to turn on a very important data integrity option: logging
# changes to the binary log between backups.
# log_bin
#
# Remove leading # to set options mainly useful for reporting servers.
# The server defaults are faster for transactions and fast SELECTs.
# Adjust sizes as needed, experiment to find the optimal values.
# join_buffer_size = 128M
# sort_buffer_size = 2M
# read_rnd_buffer_size = 2Mhost-cache-size=0
skip-name-resolve
datadir=/var/lib/mysql
socket=/var/run/mysqld/mysqld.sock
secure-file-priv=/var/lib/mysql-files
user=mysqlpid-file=/var/run/mysqld/mysqld.pid
[client]
socket=/var/run/mysqld/mysqld.sock!includedir /etc/mysql/conf.d/
bash-5.1# exit
exit[root@docker ~]# docker cp mysql01:/etc/my.cnf /opt/mysql/conf/
Successfully copied 2.56kB to /opt/mysql/conf/
[root@docker ~]# docker stop mysql01
mysql01
[root@docker ~]# docker rm mysql01
mysql01
[root@docker ~]# docker run -d \
--restart=always \
--name mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
-e MYSQL_USER=jock \
-e MYSQL_PASSWORD=123456 \
-p 3306:3306 \
-v /opt/mysql/conf/my.cnf:/etc/my.cnf \
-v /opt/mysql/conf:/etc/mysql/conf.d \
-v /opt/mysql/logs:/logs \
-v /opt/mysql/data:/var/lib/mysql \
--privileged=true \
mysql:8.4.4 \
--character-set-server=utf8mb4 \
--collation-server=utf8mb4_unicode_ci
558a6647dbb3a6ca4dcffe64eb8c4dd9a24164bbd6a370dbe6b8315799271d07
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
558a6647dbb3 mysql:8.4.4 "docker-entrypoint.s…" 5 seconds ago Up 5 seconds 0.0.0.0:3306->3306/tcp, [::]:3306->3306/tcp, 33060/tcp mysql
[root@docker ~]# docker exec -it mysql /bin/bash
bash-5.1# mysql -uroot -p123456
mysql: [Warning] Skipping '!includedir /etc/mysql/conf.d/' directive as maximum include recursion level was reached in file /etc/mysql/conf.d/my.cnf at line 32.
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.4.4 MySQL Community Server - GPLCopyright (c) 2000, 2025, Oracle and/or its affiliates.Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec)mysql> use mysql;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -ADatabase changed
mysql> show tables-> ;
+------------------------------------------------------+
| Tables_in_mysql |
+------------------------------------------------------+
| columns_priv |
| component |
| db |
| default_roles |
| engine_cost |
| func |
| general_log |
| global_grants |
| gtid_executed |
| help_category |
| help_keyword |
| help_relation |
| help_topic |
| innodb_index_stats |
| innodb_table_stats |
| ndb_binlog_index |
| password_history |
| plugin |
| procs_priv |
| proxies_priv |
| replication_asynchronous_connection_failover |
| replication_asynchronous_connection_failover_managed |
| replication_group_configuration_version |
| replication_group_member_actions |
| role_edges |
| server_cost |
| servers |
| slave_master_info |
| slave_relay_log_info |
| slave_worker_info |
| slow_log |
| tables_priv |
| time_zone |
| time_zone_leap_second |
| time_zone_name |
| time_zone_transition |
| time_zone_transition_type |
| user |
+------------------------------------------------------+
38 rows in set (0.00 sec)
docker run -d \
--restart=always \ #引擎启动自动启动
--name mysql \
-e MYSQL_ROOT_PASSWORD=123456 \ #环境变量(注意大写)
-e MYSQL_USER=jock \
-e MYSQL_PASSWORD=123456 \
-p 3306:3306 \ #暴露端口,mysql是3306,tomcat:8080,nginx:80
-v /opt/mysql/conf/my.cnf:/etc/my.cnf \
-v /opt/mysql/conf:/etc/mysql/conf.d \
-v /opt/mysql/logs:/logs \ #
-v /opt/mysql/data:/var/lib/mysql \
--privileged=true \
mysql:8.4.4 \ #
--character-set-server=utf8mb4 \ #指定格式(字符)
--collation-server=utf8mb4_unicode_ci #指定格式(整个数据库)
- 删容器
[root@docker ~]# docker stop nginx
nginx
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@docker ~]# docker rm $(docker ps -qa)
79a758674e85
fd076d79e0df
0b2b758fb52c
4c93b3094dfd
53351a84be65
f3bd91e73c0f
4467ffca57e0
3a992261f5b2
c9bc55b21a16
[root@docker ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
- 把已有的容器转换为镜像
[root@docker ~]# docker run --name nginx1 -d nginx:1.27.4
0674a3e478118bd4d27610ea4f0312eb8cb511bcc7035a9afe4db1a81359c9e9
[root@docker ~]# docker exec -it nginx1 /bin/bash
root@0674a3e47811:/# pwd
/
root@0674a3e47811:/# ls
bin docker-entrypoint.d home media proc sbin tmp
boot docker-entrypoint.sh lib mnt root srv usr
dev etc lib64 opt run sys var
root@0674a3e47811:/# cd /usr/share/nginx/html/
root@0674a3e47811:/usr/share/nginx/html# ls
50x.html index.html
root@0674a3e47811:/usr/share/nginx/html# cat index.html
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p><p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p><p><em>Thank you for using nginx.</em></p>
</body>
</html>
root@0674a3e47811:/usr/share/nginx/html# echo $(hostname)
0674a3e47811
root@0674a3e47811:/usr/share/nginx/html# echo $(hostname) $(hostname -I) > index.html
root@0674a3e47811:/usr/share/nginx/html# cat index.html
0674a3e47811 172.17.0.2
root@0674a3e47811:/usr/share/nginx/html# exit
exit
[root@docker ~]#
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0674a3e47811 nginx:1.27.4 "/docker-entrypoint.…" 2 minutes ago Up 2 minutes 80/tcp nginx1
[root@docker ~]# docker commit nginx1 mynginx:1.27.4
sha256:8626b9a7ba9aa3b02e7467a80e30e73bf3307f138e2f21b31ed677e4db4d3e44
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mynginx 1.27.4 8626b9a7ba9a 11 seconds ago 192MB
my-nginx 1.27.4 4cad75abc83d 2 months ago 192MB
nginx 1.27.4 4cad75abc83d 2 months ago 192MB
mysql 8.4.4 4a8a163431d3 2 months ago 769MB
redis 7.4.2 65750d044ac8 3 months ago 117MB
busybox latest ff7a7936e930 6 months ago 4.28MB
[root@docker ~]# docker run --name m1 -d -p 80:80 mynginx:1.27.4
3edf6bddb8b910eb3e7d4502763e450b7c7c203c7492346f41cd9fe98e92bcd3
[root@docker ~]# docker exec -it m1 cat /usr/share/nginx/html/index.html
0674a3e47811 172.17.0.2