Skip to content

基础概念

NOTE

容器共享主机内核,轻量、隔离并且高效,不像虚拟机需要完整的操作系统。

  • 容器 Container 轻量化运行的实例,包含应用代码、运行时环境和依赖库。基于镜像创建,与其他容器隔离,共享主机操作系统内核(比虚拟机更高效)
  • 镜像 Image 只读模板,定义了容器的运行环境(如操作系统、软件配置)。通过分层存储(Layer),优化空间和构建速度。
  • Dockerfile 文本文件、描述如何自动构建镜像,例如基础镜像、安装软件、复制文件等。
  • 仓库 Registry 存储和分发镜像的平台,比如 Docker Hub

alt text

安装 (基于 CentOS 系统)

安装指南

sh
sudo dnf -y install dnf-plugins-core
sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo dnf install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

直接使用官方镜像拉取,大概率是下载不成功的,可以考虑使用国内的镜像源 具体参考

sh
# 执行该指令切换为清华大学镜像源
sed -i 's+https://download.docker.com+https://mirrors.tuna.tsinghua.edu.cn/docker-ce+' /etc/yum.repos.d/docker-ce.repo

安装完成后启动,并设置开机启动

sh
systemctl start docker.service
systemctl enable docker.service

安装完成后仍然需要配置镜像源,不然镜像拉取也是费劲 参考

容器与镜像的关系

NOTE

  • 镜像 容器的静态模板,包含了应用程序运行所需要的一来和文件,镜像是不可变的。

  • 容器 镜像的一个运行实例,具有自己的文件系统、进程、网络等且是动态的。容器从镜像启动,并在运行时保持可变。

镜像基本操作

命令作用
docker image ls | docker images列出所有镜像
docker pull [镜像名]拉取镜像
docker push [镜像名]推送镜像
docker build根据 Dockerfile 构建镜像
docker rmi [镜像名]删除镜像
docker image prune删除所有未使用的镜像,没有标记或者没有任何容器引用
docker search [镜像名]查找镜像
docker history [镜像名]查看镜像历史
docker inspect [镜像名 | 容器名]显示镜像或者容器详细信息
docker tag [镜像名] [标签/镜像名]为镜像打标签,只是别名,不会占用额外存储空间
docker save -o 文件.tar 镜像名将镜像打包为 tar 文件
docker load -i [镜像名].tar从 tar 文件中加载镜像

容器基本操作

如果你实在是忘记了后面的参数,可以使用 docker [command] --help 查看具体的用法。

命令作用
docker run [容器ID/容器名]
docker container run [容器ID/容器名]
启动容器
docker build构建镜像
docker logs查看容器的日志
docker ps列出当前正在运行的容器
docker stop [容器ID/容器名]
docker start [容器ID/容器名]
docker restart [容器ID/容器名]
容器启停
docker stats [容器ID/容器名]显示容器资源统计,不指定默认查看所有
docker rm [容器ID/容器名]删除停止的容器
docker rename [容器ID/容器名] [新容器名]容器重命名
docker container prune删除所有停止的容器
docker exec [容器ID/容器名]在运行的容器中执行指令
docker attach [容器ID/容器名]运行中的容器中附加终端
docker login登录DockerHub
docker logout登出DockerHub
docker export [容器ID/容器名]导出容器的文件系统为 tar 文件,主要用于备份迁移容器的文件系统
docker import导入 tar 文件为镜像,其实是属于镜像操作了
docker commit [容器ID/容器名] [镜像名:标签]创建镜像

docker run

  • -d 后台运行
  • -it 交互式
  • -p 端口映射
  • -P 随机映射端口
  • --name 给容器指定一个名字
  • --env | -e 设置环境变量
bash
# 启动 ubuntu 容器后台运行
docker run -d ubuntu

# 交互式启动 ubuntu 容器,并且指定终端的 shell 是 bin/bash
docker run -it ubuntu /bin/bash

# 将容器的 80 端口映射到主机的 3000 端口,后台启动 ngxin 容器
docker run -d -p 3000:80 nginx

# 随机映射一个端口
docker run -d -P nginx

# 设置环境变量
docker run -e MY_ENV_VAR=my_value ubuntu

# 设置容器名称
docker run -d --name web_service nginx

docker build

docker build [OPTIONS] PATH | URL | -

  • PATH: 包含 Dockerfile 的路径或者 . 当前目录
  • URL: 包含 Dockerfile 的远程仓库地址
  • -: 从标准输入中读取 Dockerfile

常用选项

  • -t | --tag:为构建的镜像指定名称和标签
  • -f | --file: 指定 Dockerfile 的路径(默认是 PATH 下的 Dockerfile
  • --build-arg: 设置构建参数
  • --no-cache: 构建镜像过程中不使用缓存

以简单的 express 服务器为例,构建镜像。Dockerfile 内容如下

bash
# Dockerfile
FROM node:20.5.0-alpine

WORKDIR /app
COPY . .
RUN npm install
CMD [ "npm", "run", "dev" ]

# 构建镜像
docker build --no-cache -t express-server .
# 构建之后使用 docker images 就会出现名称为 express-server 的镜像
# 运行镜像就可以访问 3000 端口查看 express 服务了。
docker run -d -p 3000:3000 express-server 

# 传递传输时,在 Dockerfile 中可以使用以下方式进行访问。
# RUN echo "Build argument MY_ARG is: ${MY_ARG}"
docker build --build-arg MY_ARG=my-value -t express-server .

docker logs

  • -f 类似于 tail -f
  • -t 显示日志时间戳
  • --tail 仅显示日志的最后部分,比如 --tail 10
bash
docker logs -f -t --tail 10 web_service

docker ps

默认查看所有运行中的容器

  • -l:显示最近创建的容器,包含所有状态
  • -a:显示所有容器,包含所有状态
  • -n:显示最近创建的 n 个容器,包含所有状态
  • -s:显示容器的大小

容器的状态有 7 中

状态说明
created创建完成,但还没有启动
running正在运行
paused暂停
exited退出
dead挂起
restarting重启中
removed删除
bash
# 显示最近创建的 5 个容器
docker ps -n 5

docker rm

  • -f 强制删除正在运行的容器,使用 SIGKILL 9 信号
bash
docker rm -f web_service

docker commit

-a 添加作者 -m 添加描述 -p 提交镜像前暂停容器,默认 true

bash
docker commit -a "author" -m "description" web_service web_service:v1

docker run -d web_service:v1

docker export & docker import

-o 将输出保存到指定文件

bash
# 打包出来内容是 容器的文件系统。包含 /app 目录
docker export -o node-service.tar node_service

# 将导出的 tar 再导入到 docker image 中
# !!! 但是 导入的镜像不一定就可以运行,因为导出的只是文件系统,可能会缺少一些元数据
# 可以使用 commit 将容器提交为镜像,在配合 save 和 load 去做个事情。
docker import node-service.tar node-service

docker exec & docker attach

  • -it 交互式,输出 exit 退出, attach 没有这些参数。

execattach 最大的区别就是 exec 不会停止容器,attach 会将容器停止。

bash
# 进入容器内部,容器内部就是一个完整的 linux 环境 并指定终端的 shell
docker exec -it web_service /bin/bash

docker exec -it web_service ls /app # 列出 app 目录下的文件
docker exec -it web_service touch /app/test.txt # 创建一个 test.txt 文件

卷操作 volume

用于持久化数据数据的文件系统,可以在容器之间的数据共享和复用。当容器停止或者被删除时,数据仍然会被保留。

指令说明
docker volume create [ 卷名 ]创建一个卷
docker volume ls列出所有卷
docker volume inspect [ 卷名 ]查看卷信息
docker volume rm [ 卷名 ]删除一个卷或多个卷
docker volume prune删除所有未使用的卷
bash
docker volume create node-logger
# 查看卷的详细信息
docker volume inspect node-logger
# [
#     {
#         "CreatedAt": "2025-07-31T19:04:31+08:00",
#         "Driver": "local",
#         "Labels": null,
#         "Mountpoint": "/var/lib/docker/volumes/node-logger/_data",
#         "Name": "node-logger",
#         "Options": null,
#         "Scope": "local"
#     }
# ]

docker volume ls
# DRIVER    VOLUME NAME
# local     node-logger

# 删除卷 
docker volume rm node-logger node-logger-1 node-logger-2 ...

在执行 docker run 的时候可以指定 volume 的挂载方式,有三种如下:

  • Bind Mount: 绑定到主机文件系统,只有手动清理数据才会消失。
  • Named VolumeDocker 存储目录,docker volume rm 后会自动删除。
  • Tmpfs Mount:数据在内存中,当 docker stop 数据丢失。

默认情况下如果什么参数也没有,则是 Docker 自动创建可写的容器层,只有执行 docker rm 的时候,数据才会被删除。

Bind Mount

绑定到主机的文件系统,每个容器运行起来其实就是一个完整的 linux 系统。此操作就是将容器内的某个文件夹和外部的做出绑定,有点类似于软连接

bash
# 启动 service:v1 容器,指定容器名,并且将系统的 tmp 和 容器的 tmp 绑定。
# -v 前面是主机路径,后面是容器内路径
docker run --name bind-mount -v /tmp:/tmp -d service:v1

# 此时 /tmp 的任何变动都会被同步,达到持久化的目的。只能手动清理
# 可以通过以下指令进入容器内部,测试效果
docker exec -it bind-mount /bin/bash

Named Volume

使用 docker volume 创建数据卷进行绑定。只要数据卷不被删除,数据就会被保留。同时存在两份,一份在容器内,一份在宿主机。

bash
docker volume create named_volume
# 需要查看 inspect 中的 Mountpoint 地址
docker volume inspect named_volume

# -v 前面是数据卷名称,后面是数据卷地址
docker run --name named-volume -v named_volume:/var/lib/docker/volumes/named_volume/_data -d service:v1

Tmpfs Volume

bash
docker run --tmpfs /tmp:rw,size=100m -d alpine

# 也可以不指定,这样可能会把内存占满
docker run --tmpfs /tmp -d alpine