Docker主要解决的问题:
inux 容器不是模拟一个完整的操作系统,而是对进程进行隔离。或者说,在正常进程的外面套了一个保护层。对于容器里面的进程来说,它接触到的各种资源都是虚拟的,从而实现与底层系统的隔离
特点
核心内核技术
1.命名空间
2.控制组
3.容器文件系统
+------------------+ +-------------------+ +-------------------+
| | | | | |
| Docker Client | <---> | Docker Daemon | <---> | Docker Registry |
| (CLI, API) | | (dockerd + runc) | | (Docker Hub, etc) |
+------------------+ +---------+---------+ +---------+---------+
| |
| v
| +-------------------+
| | Docker Images |
| +---------+---------+
| |
| v
| +---------+---------+
| | Containers |
| +---------+---------+
| |
| v
| +---------+---------+
| | Docker Engine |
| | (containerd, runc,Shim)|
+-------------------+
docker
命令行工具。docker run
、docker build
)。ubuntu:20.04
镜像包含 Ubuntu 系统的基础环境。docker run
创建,依赖 containerd 和 runc 启动。在windows、MacOS上运行Docker,其实本质上是借助了虚拟化技术,然后在linux虚拟机上运行的Docker程序。
// 安装依赖和存储驱动相关包
yum install -y yum-utils device-mapper-persistent-data lvm2
作用:安装 Docker 所需的依赖包和存储驱动支持。
yum-utils
:提供 yum-config-manager
等工具,用于管理 YUM 仓库。device-mapper-persistent-data
和 lvm2
:
这些是 设备映射器(Device Mapper) 存储驱动的依赖项。Docker 默认使用 overlay2
存储驱动,但如果系统不支持 overlay2
(例如旧版内核),可能会回退到 devicemapper
。// 添加 Docker 阿里云 官方仓库
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
containerd.io
的 RPM 包。--add-repo
:直接通过 URL 添加仓库,无需手动下载 .repo
文件。# 清除缓存并重试安装
sudo yum clean all
sudo yum makecache
sudo yum install -y docker-ce
docker-ce
:Docker 社区版引擎(核心组件,负责容器管理)。 systemctl start docker
systemctl enable docker # 开机自启
docker version
docker info
# 创建配置文件(若不存在)
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": [
"https://mirrors.tencent.com",
"https://image.cloudlayer.icu",
"https://hub.fast360.xyz",
"https://docker-0.unsee.tech"
]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
docker info | grep -A5 "Registry Mirrors" # 应显示配置的镜像源
docker info 警告
docker info | grep "Registry Mirrors"
WARNING: bridge-nf-call-iptables is disabled
WARNING: bridge-nf-call-ip6tables is disabled
# 永久生效
cat <<EOF | sudo tee -a /etc/sysctl.conf
net.bridge.bridge-nf-call-iptables=1
net.bridge.bridge-nf-call-ip6tables=1
EOF
sudo sysctl -p
sudo modprobe br_netfilter
echo "br_netfilter" | sudo tee /etc/modules-load.d/br_netfilter.conf
!
Docker-CE和Docker-EE
docker history <ID/NAME>
查看镜像中各层内容及大小,docker load
来导入镜像存储文件到本地镜像库,也可以使用 docker import
来导入一个容器快照到本地镜像库命令 | 含义 | 语法 | 案例 |
---|---|---|---|
ls | 查看全部镜像 | docker image ls | |
search | 查找镜像 | docker search imageName | |
history | 查看镜像历史 | docker history imageName | |
inspect | 显示一个或多个镜像详细信息 | docker inspect imageName | |
pull | 拉取镜像 | docker pull imageName | |
push | 推送一个镜像到镜像仓库 | docker push imageName | |
rmi | 删除镜像 | docker rmi imageName docker image rmi 2 | |
prune | 移除未使用的镜像,没有标记或补任何容器引用 | docker image prune | docker image prune |
tag | 标记本地镜像,将其归入某一仓库 | docker tag OPTIONS IMAGE:TAGUSERNAME/NAME:TAG | docker tag centos:7 zhangrenyang/centos:v1 |
export | 将容器文件系统作为一个tar归档文件导出到STDOUT | docker export OPTIONS CONTAINER | docker export -o hello-world.tar b2712f1067a3 |
import | 导入容器快照文件系统tar归档文件并创建镜像 | docker import OPTIONS file/URL/- [REPOSITORY:TAG] | docker import hello-world.tar |
save | 将指定镜像保存成 | docker save OPTIONS IMAGE IMAGE... | docker save -o hello-world.tar hello-world:latest |
load | 加载tar文件并创建镜像 | docker load -i hello-world.tar | |
build | 根据Dockerfile构建镜像 | docker build OPTIONS PATH / URL / - | docker build -t zf/ubuntu:v1 . |
# 搜索 centos
docker search centos
# 搜索 hello-world
docker search hello-world
# 查看所有本地存储的镜像。
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mongo 6.0 4f3dbc8f2775 5 weeks ago 747MB
bitnami/redis latest f7f358889b53 2 months ago 145MB
mysql 8.3.0 6f343283ab56 14 months ago 632MB
# 查看指定
docker images mysql
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql 8.3.0 6f343283ab56 14 months ago 632MB
# 下载 centos
docker pull centos
# 下载 hello-world
docker pull hello-world
# 删除 hello-world
docker rmi hello-world
Untagged: hello-world:latest
# 如果有多个版本hello-world 会删除 最新的hello-world
# docker rmi hello-world 等价 docker rmi hello-world:last
# 语法 备份 mysql (redis_image.tar文件名称)
docker save -o redis_image.tar mysql
#
docker load -i redis_image.tar
# 重命名
# 如果centos名称有,就把原有的镜像指向新名称,如果原有名称none 就会覆盖
docker tag centos centos:7.4
docker image inspect centos
什么是容器
容器(Container):容器是一种轻量级、可移植、并将应用程序进行的打包的技术,使应用程序可以在几乎任何地方以相同的方式运行.
docker run
命令会从 image
文件,生成一个正在运行的容器实例。docker container run
命令具有自动抓取 image 文件的功能。如果发现本地没有指定的 image 文件,就会从仓库自动抓取命令 | 含义 | 案例 | |
---|---|---|---|
run | 从镜像运行一个容器 | docker run ubuntu /bin/echo 'hello-world' | |
ls | 列出容器 | docker container ls | |
inspect | 显示一个或多个容器详细信息 | docker inspect | |
attach | 要attach上去的容器必须正在运行,可以同时连接上同一个container来共享屏幕 | docker attach OPTIONS CONTAINER | docker attach 6d1a25f95132 |
stats | 显示容器资源使用统计 | docker container stats | |
top | 显示一个容器运行的进程 | docker container top | |
update | 更新一个或多个容器配置 | docker update -m 500m --memory-swap -1 6d1a25f95132 | |
port | 列出指定的容器的端口映射 | docker run -d -p 8080:80 nginx docker container port containerID | |
ps | 查看当前运行的容器 | docker ps -a -l | |
kill containerId | 终止容器(发送SIGKILL ) | docker kill containerId | |
rm containerId | 删除容器 | docker rm containerId | |
start containerId | 启动已经生成、已经停止运行的容器文件 | docker start containerId | |
stop containerId | 终止容器运行 (发送 SIGTERM ) | docker stop containerId docker container stop $(docker container ps -aq) | |
logs containerId | 查看 docker 容器的输出 | docker logs containerId | |
exec containerId | 进入一个正在运行的 docker 容器执行命令 | docker container exec -it f6a53629488b /bin/bash | |
cp containerId | 从正在运行的 Docker 容器里面,将文件拷贝到本机 | docker container cp f6a53629488b:/root/root.txt . | |
commit containerId | 根据一个现有容器创建一个新的镜像 | docker commit -a "zhufeng" -m "mynginx" a404c6c174a2 mynginx:v1 |
https://cloud.tencent.com.cn/developer/article/2236303
# 创建容器名为wo-mysql, 表示容器启动后执行ls命令 参数 -a
docker create --name wo-mysql mysql:8.3.0 ls -a
# docker-entrypoint.sh 是 Docker 容器启动时执行的脚本,通常用于初始化容器的环境设置
NAMES IMAGE COMMAND STATUS
mysql:8.3.0 mysql:8.3.0 "docker-entrypoint.sh ls -a" Created
#-t(--tty)表示为容器分配一个伪终端(TTY),通常用于与容器进行交互式会话。
#(--interactive)表示以交互模式启动容器,允许你在容器内执行命令。如果你在命令行启动 MySQL 容器时加上 -ti,它意味着你可以在容器内交互
docker create -ti --name wo-mysql2 mysql:8.3.0
# 容器启动 wo-mysql
docker start wo-mysql
# STATUS(容器状态) 从 Created(创建)到很快Exited(退出)状态,是因为ls -a 命令很快执行完了
IMAGE COMMAND STATUS NAMES
mysql:8.3.0 "docker-entrypoint.s…" Exited (0) 24 seconds ago wo-mysql
# 容器启动 -a 把容器输出结果,展示到当前shell
C:\Users\sunmeng>docker start -a wo-mysql
.
..
.dockerenv
bin
boot
dev
docker-entrypoint-initdb.d
etc
home
lib
lib64
media
#执行容器wo-mysql2 通过创建时候传入 -ti,允许你在容器内执行命令mysql
docker start -a wo-mysql2
2025-05-27 02:21:04+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.3.0-1.el8 started.
2025-05-27 02:21:05+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
2025-05-27 02:21:05+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.3.0-1.el8 started.
2025-05-27 02:21:05+00:00 [ERROR] [Entrypoint]: Database is uninitialized and password option is not specified
You need to specify one of the following as an environment variable:
# 指定一个密码来初始化 root 用户(推荐)
- MYSQL_ROOT_PASSWORD
# 允许使用空密码(不推荐,除非你知道自己在做什么)
- MYSQL_ALLOW_EMPTY_PASSWORD
- MYSQL_RANDOM_ROOT_PASSWORD
# docker run == docker create + docker start -a 前台模式
# docker run -d === docker create + docker start 后台模式
# 创建并启动 mysql:8.3.0
docker run mysql:8.3.0
2025-05-27 02:39:07+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.3.0-1.el8 started.
2025-05-27 02:39:07+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
2025-05-27 02:39:07+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.3.0-1.el8 started.
2025-05-27 02:39:07+00:00 [ERROR] [Entrypoint]: Database is uninitialized and password option is not specified
You need to specify one of the following as an environment variable:
- MYSQL_ROOT_PASSWORD
- MYSQL_ALLOW_EMPTY_PASSWORD
- MYSQL_RANDOM_ROOT_PASSWORD
# 创建时候没有传名称,所以docker随机生成名称 vibrant_hawking
docker ps -a
IMAGE COMMAND CREATED STATUS NAMES
mysql:8.3.0 "docker-entrypoint.s…" 8 seconds ago Exited (1) 6 seconds ago vibrant_hawking
# 现在后台运行 b-express-mysql-1容器 端口3306
IMAGE COMMAND STATUS PORTS NAMES
mysql:8.3.0 "docker-entrypoint.s…" Up 21 seconds 0.0.0.0:3306->3306/tcp, 33060/tcp b-express-mysql-1
# 关闭 b-express-mysql-1
docker stop b-express-mysql-1
# 常用场景:当容器无法响应 SIGTERM,或者在某些情况下需要立即停止容器时使用
docker kill <container_name_or_id>
特性 |
|
|
---|---|---|
停止方式 | 向容器发送 | 向容器发送 |
容器响应 | 容器可以捕获并处理 | 容器无法捕获 |
使用场景 | 优雅关闭容器,常用于生产环境 | 强制停止容器,常用于容器无法正常停止时 |
默认超时 | 默认 10 秒(可以通过 | 无超时,立即强制停止容器 |
# 运行容器 b-express-mysql-1
docker start b-express-mysql-1
# 查看运行容器
docker ps
# 状态运行
IMAGE COMMAND STATUS NAMES
mysql:8.3.0 "docker-entrypoint.s…" Up 10 seconds b-express-mysql-1
# 容器暂停
docker pause b-express-mysql-1
# 状态暂停
docker ps
IMAGE COMMAND STATUS NAMES
mysql:8.3.0 "docker-entrypoint.s…" Up 36 seconds (Paused) b-express-mysql-1
# 取消暂停
docker unpause <container_name_or_id>
# 删除
docker rm <container_name_or_id>
#强制删除
docker rm -f <container_name_or_id>
#基本语法
docker restart <container_name_or_id>
# 基本语法
docker attach <container_name_or_id>
# 1. 连接到标准输入输出:连接后,你会看到容器内正在运行的应用程序的输出,并且你可以通过输入来与容器进行交互(如果容器内有交互式命令)
# 2. 退出连接:如果你希望退出容器的连接,你可以按 Ctrl + C 或 Ctrl + P 然后 Ctrl + Q,以便返回到主机终端,但不会停止容器
# 进入 MySQL 容器的命令行(b-express-mysql-1 容器名称)
docker exec -it b-express-mysql-1 bash
特性 | 镜像 (Images) | 容器 (Containers) |
---|---|---|
状态 | 静态,只读 | 动态,可写 |
存储 | 分层存储 | 镜像层+可写层 |
生命周期 | 持久存在 | 运行(临时)/停止(保留状态) |
变更 | 不可变更 | 可修改文件系统和配置 |
类比 | 软件的安装程序 | 软件正在运行 |
创建方式 | 构建、提交、拉取 | 基于镜像运行 |
占用资源 | 磁盘空间 | CPU、内存、磁盘 |
数量关系 | 一个镜像可以创建多个容器 | 多个容器可共享同一镜像 |
# 运行容器 centos
docker run -dti centos bash
# 查看容器
docker ps -a
# 查看结果
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
aa562037700b centos "bash" 26 seconds ago Up 25 seconds sweet_stonebraker
#在容器centos 安装net-tools工具包
[root@lavm-zo7f3xq5c6 ~]# docker exec aa56 yum install -y net-tools
# 查看容器centos ifconfig
docker exec aa56 ifconfig
# 输出结果
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet)
RX packets 11333 bytes 17635289 (16.8 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 7759 bytes 474305 (463.1 KiB)
# 容器提交
docker commit -m 'install net-tools' aa56 coentos-net:v1.0
sha256:b46656d01be91ced0fbc7154dac16e7f25af906be00adb044d1af087b8a811f5
# 查看镜像
docker images
# 查看结果
REPOSITORY TAG IMAGE ID CREATED SIZE
coentos-net v1.0 b46656d01be9 6 minutes ago 342MB
nginx latest be69f2940aaf 6 weeks ago 192MB
centos latest 9f38484d220f 6 years ago 202MB
# coentos-net 生成的镜像
# 查看容器
docker ps -a
# 查看容器结果
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
aa562037700b centos "bash" 44 minutes ago Up 44 minutes sweet_stonebraker
# 容器导出
docker export -o net-tools-image.tar aa56
# 查看目录
ls
# 查看目录结果
anaconda-ks.cfg net-tools-image.tar
#导入
docker import -m '(import) install net-tools' net-tools-image.tar centos-netv2:1.0
[root@lavm-zo7f3xq5c6 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos-netv2 1.0 6d0baed20aad 6 seconds ago 319MB
coentos-net v1.0 b46656d01be9 50 minutes ago 342MB
nginx latest be69f2940aaf 6 weeks ago 192MB
centos latest 9f38484d220f 6 years ago 202MB
核心对比
特性 |
|
|
---|---|---|
输入源 | 正在运行的容器 | 文件系统压缩包( |
输出 | 带历史层的新镜像 | 单层基础镜像 |
保留元数据 | ✅ ( | ❌ (需手动指定) |
分层结构 | ✅ (新增层叠加在原镜像之上) | ❌ (整个文件系统作为单一层) |
如何选择?
docker commit
docker import
Docker 镜像采用分层存储结构,每个层(Layer)都是只读的文件系统快照。这种设计是 Docker 的核心优化之一。
关键特性
# 查看镜像分层
docker image inspect nginx:alpine --format='{{.RootFS.Layers}}'
alpine
层),节省磁盘空间。分层示例(以 python:3.9
镜像为例):
Layer 4: pip install -r requirements.txt # 应用依赖层(只读)
Layer 3: COPY app.py /app/ # 代码层(只读)
Layer 2: RUN apt-get install gcc # 编译工具层(只读)
Layer 1: FROM debian:buster-slim # 基础操作系统层(只读)
容器在运行时依赖于镜像的分层结构,但添加了独有的可写层,这是容器动态性的核心
一个运行中的容器由两部分组成:
┌───────────────────────────────┐
│ 容器实例 (Container) │
├───────────────────────────────┤
│ ╔═════════════════════════╗ │
│ ║ 可写层 (容器层) ║ │ ← 容器运行时创建,存储所有修改
│ ║ (Container Layer) ║ │
│ ╚═════════════════════════╝ │
│ ┌──────────────────────────┐ │
│ │ 镜像层 (只读) │ │
│ │ (Image Layers) │ │ ← 来自基础镜像和应用镜像
│ └──────────────────────────┘ │
└───────────────────────────────┘
特性 | 说明 |
---|---|
位置 | 位于所有镜像层之上(堆叠结构的最顶层) |
读写权限 | 唯一可写层,所有文件修改(增删改)均发生在此层 |
生命周期 | 随容器创建而生成,随容器删除而销毁( |
存储驱动 | 由 Docker 配置的存储驱动管理(如 Overlay2、AUFS、Btrfs) |
写时复制 (CoW) | 首次修改文件时,从镜像层复制文件到容器层,原始镜像层保持不变 |
数据隔离 | 每个容器拥有独立的容器层,互不影响 |
文件修改场景(写时复制示例)
A
,Docker 先将 A
复制到容器层,再修改容器层中的副本。A
保持不变。关键技术:联合文件系统(UnionFS)
Docker 使用 Overlay2/AUFS 等联合文件系统将多层文件合并为单一视图:
/
目录)# 1. 创建容器
docker run -d --name test nginx:alpine
# 2. 查看联合挂载点
docker inspect test --format='{{.GraphDriver.Data}}'
# 输出示例:
{
"LowerDir": "/var/lib/docker/overlay2/xx...xx/diff",
"MergedDir": "/var/lib/docker/overlay2/xx...xx/merged",
"UpperDir": "/var/lib/docker/overlay2/xx...xx/diff",
"WorkDir": "/var/lib/docker/overlay2/xx...xx/work"
}
当执行 docker run
时发生的过程:
ENTRYPOINT
/CMD
(如 /docker-entrypoint.sh nginx
)docker logs
捕获)原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有