FORMA

容器、数据与网络

容器是镜像的运行实例。掌握容器的创建、管理、进入、日志查看等命令是使用 Docker 的日常核心;再结合数据卷(持久化)网络(通信),才能搭建出可用于生产的容器化服务。镜像基础见 镜像与 Dockerfile

一、容器基础操作

1. 创建并运行容器

最常用的命令是 docker run,它先拉取镜像(如果本地没有),然后创建并启动容器。

bash
# 运行一个 nginx 容器,后台运行,命名为 my-nginx,将宿主机的 8080 端口映射到容器的 80 端口
docker run -d --name my-nginx -p 8080:80 nginx

常用参数

参数说明
-d后台运行(detach),容器在后台运行,不占用当前终端
--name为容器指定一个名字,方便后续管理
-p端口映射,格式 宿主机端口:容器端口,可多次使用
-it交互式运行(例如进入容器执行 shell 时需要 -it
--rm容器退出后自动删除(常用于临时任务)
-v挂载数据卷(宿主机目录:容器目录),见下文数据管理
-e设置环境变量,如 -e MY_VAR=value
--restart重启策略,如 --restart unless-stopped(生产环境常用)、alwayson-failure:3
--network指定加入的网络,见下文网络部分
--memory / --cpus限制内存、CPU 资源,防止单容器耗尽宿主机资源

2. 进入运行中的容器(交互式 shell)

bash
# 进入正在运行的容器,执行 /bin/bash(若容器内没有 bash 可用 /bin/sh)
docker exec -it my-nginx /bin/bash

# 对于 alpine 系统(如 nginx:alpine),使用 /bin/sh
docker exec -it my-nginx /bin/sh
  • -it 分配伪终端并保持 STDIN 打开,这样才能交互。
  • 退出容器:输入 exit 或按 Ctrl+D(不会影响容器本身的运行,因为 exec 只是附加了一个新进程)。

3. 查看容器

bash
# 查看正在运行的容器
docker ps

# 查看所有容器(包括已停止的)
docker ps -a

# 查看最后创建的 5 个容器
docker ps -n 5

# 只显示容器 ID
docker ps -q

4. 停止、启动、重启、删除容器

bash
# 停止容器(发送 SIGTERM,超时后 SIGKILL)
docker stop my-nginx

# 启动已停止的容器
docker start my-nginx

# 重启容器
docker restart my-nginx

# 删除已停止的容器
docker rm my-nginx

# 强制删除正在运行的容器(会先停止再删除)
docker rm -f my-nginx

# 删除所有已停止的容器
docker container prune

提示docker rm 时如果容器正在运行,需要先 stop 或使用 -f

5. 查看容器日志

bash
# 输出全部日志
docker logs my-nginx

# 实时跟踪日志(类似 tail -f)
docker logs -f my-nginx

# 只看最后 100 行
docker logs --tail 100 my-nginx

# 并加上时间戳
docker logs -t my-nginx

6. 查看容器内进程与资源

bash
docker top my-nginx      # 类似 ps aux,显示容器内运行的进程
docker stats my-nginx    # 实时查看 CPU、内存、网络、I/O 使用情况
docker inspect my-nginx  # 查看详细配置信息(IP、挂载、网络、环境变量等)

7. 在宿主机和容器之间复制文件

bash
# 将宿主机文件复制到容器的指定路径
docker cp ./index.html my-nginx:/usr/share/nginx/html/

# 从容器的路径复制到宿主机
docker cp my-nginx:/etc/nginx/nginx.conf ./nginx.conf
  • 路径可以是绝对路径或相对于当前目录。
  • 对运行中或已停止的容器都有效。

8. 其他常用容器操作

命令说明
docker logs -f my-nginx | grep "error"过滤日志中的错误信息
docker rename old-name new-name重命名容器
docker wait my-nginx阻塞等待容器停止,返回退出码
docker update --restart always my-nginx运行时修改重启策略等配置
docker container inspect --format '{{.State.Health.Status}}' my-nginx查看 HEALTHCHECK 健康状态

容器操作总结表

操作命令
创建并后台运行docker run -d --name <name> <image>
端口映射-p 8080:80
进入容器docker exec -it <container> /bin/bash
查看运行容器docker ps
停止/启动/重启docker stop/start/restart <container>
删除容器docker rm <container>
查看日志docker logs -f <container>
文件复制docker cp <src> <dest>

掌握这些基础命令,即可在开发或测试环境中灵活管理 Docker 容器。对于生产环境,还需结合下面的数据卷、网络等高级特性。

二、数据管理(卷与挂载)

默认情况下,容器内的数据是临时的:当容器被删除,其中产生的数据也会丢失。为了持久化数据或在多个容器之间共享数据,Docker 提供了三种挂载方式:

  • 绑定挂载(Bind Mount):将宿主机上的任意目录或文件挂载到容器内。
  • 卷(Volume):由 Docker 管理的数据存储区域,独立于容器生命周期。
  • 临时文件(tmpfs):存储在宿主机内存中,不会写入磁盘,容器停止后即丢失。

1. 绑定挂载(Bind Mount)

将宿主机上的特定目录或文件映射到容器内。适合开发环境,因为可以直接在宿主机修改代码,容器内立即生效。

基本语法

bash
docker run -v /宿主机/绝对路径:/容器内路径:选项 镜像名

或使用新版 --mount 语法(更明确)。

示例

bash
# 将宿主机的当前目录下的 html 文件夹挂载到容器的 /usr/share/nginx/html
docker run -d -p 8080:80 -v $(pwd)/html:/usr/share/nginx/html nginx

# 只读挂载,容器内无法修改(追加 :ro)
docker run -d -v $(pwd)/html:/usr/share/nginx/html:ro nginx

特点

  • 依赖宿主机的目录结构,可移植性较差。
  • 容器可以直接读写宿主机文件(权限可能受限,Linux 下注意宿主机与容器内用户 UID 是否一致)。
  • 可用于配置注入、代码热加载等。

2. 卷(Volume)

完全由 Docker 管理,存放在 Docker 存储目录下(Linux 为 /var/lib/docker/volumes/)。适合生产环境,数据独立于容器,且便于备份和迁移。

创建和使用卷

bash
# 创建卷
docker volume create mydata

# 使用卷运行容器(-v 卷名:容器内路径)
docker run -d -v mydata:/app/data alpine

# 也可以不预先创建,在 run 时隐式创建
docker run -d -v mydata2:/app/data alpine

管理卷

bash
docker volume ls               # 列出所有卷
docker volume inspect mydata   # 查看卷详细信息(包括挂载点)
docker volume rm mydata        # 删除指定卷
docker volume prune            # 删除所有未被任何容器使用的卷

备份与恢复示例(借助临时容器打包卷内容):

bash
# 备份:将 mydata 卷内容打包为宿主机当前目录下的 backup.tar.gz
docker run --rm -v mydata:/data -v $(pwd):/backup alpine \
  tar czf /backup/backup.tar.gz -C /data .

# 恢复:将 backup.tar.gz 解压回一个新卷
docker run --rm -v mydata_restored:/data -v $(pwd):/backup alpine \
  tar xzf /backup/backup.tar.gz -C /data

特点

  • 支持卷驱动(如本地、NFS、云存储)。
  • 可以在多个容器之间共享。
  • 备份和恢复简单(直接复制卷的目录,或如上用临时容器打包)。

3. 临时文件(tmpfs)

将数据存储在宿主机的内存中,不会写入磁盘。容器停止或删除后,数据即丢失。适合存放临时、敏感、不持久化的数据(如缓存、密钥)。

语法

bash
docker run -d --tmpfs /容器内路径 镜像名

示例

bash
docker run -d --name temp-test --tmpfs /app/temp alpine sleep 300

特点

  • 速度快(内存读写)。
  • 容器重启后数据清空。
  • 不占用磁盘空间。

4. 三种方式对比

特性绑定挂载(Bind Mount)卷(Volume)tmpfs
数据存储位置宿主机任意目录Docker 管理的路径宿主机内存
持久性是(宿主机文件不变则持久)否(容器停止即失效)
管理方式用户手动管理Docker 命令管理仅运行时挂载
适用环境开发环境生产环境临时缓存/敏感数据
可移植性低(依赖具体路径)高(卷可命名、备份)不适用跨容器持久化
性能接近原生文件系统接近原生文件系统内存速度,但受限内存大小

5. 使用 --mount 语法(推荐)

--mount-v 更明确、可读性更高,语法错误时会直接报错(而 -v 在路径不存在时可能被静默当作卷名创建)。

绑定挂载示例

bash
docker run -d --mount type=bind,source="$(pwd)/html",target=/usr/share/nginx/html nginx

卷示例

bash
docker run -d --mount source=mydata,target=/app/data alpine

tmpfs 示例

bash
docker run -d --mount type=tmpfs,target=/app/temp alpine

数据管理小结

  • 开发调试:使用绑定挂载,实时同步代码。
  • 生产持久化:使用卷,数据独立、易备份。
  • 临时数据:使用 tmpfs,避免磁盘写入,提高性能。

三、网络基础

Docker 提供了多种网络驱动,使容器之间、容器与宿主机之间能够通信。默认安装后 Docker 会自动创建三种网络:bridge(默认)、hostnone

1. 查看网络

bash
docker network ls

输出示例:

text
NETWORK ID     NAME      DRIVER    SCOPE
abc123def456   bridge    bridge    local
789ghi012jkl   host      host      local
345mno678pqr   none      null      local
  • bridge:默认网络,容器启动时不指定网络则加入此网络。同一 bridge 网络内的容器可以通过 IP 互相访问,但不能通过容器名直接访问(自定义桥接网络才支持容器名解析)。
  • host:容器直接使用宿主机的网络栈,没有网络隔离,性能好但端口易冲突(Windows/macOS 上的 Docker Desktop 因运行在虚拟机内,host 网络行为与 Linux 有差异)。
  • none:容器没有网络接口(仅 loopback),完全隔离,适合无需联网的批处理任务。

2. 创建自定义桥接网络(推荐)

bash
docker network create mynet
  • 自定义网络支持内置 DNS 解析:同一网络中的容器可以通过容器名互相 ping 通,无需使用 --link
  • 可以指定子网、网关等:docker network create --subnet=172.20.0.0/24 mynet

3. 在自定义网络中运行容器(通过容器名通信)

bash
# 启动两个容器,都连接到 mynet
docker run -d --name app1 --network mynet nginx
docker run -d --name app2 --network mynet nginx

# 进入 app1 容器测试能否使用 app2 名称 ping 通
docker exec -it app1 bash
apt update && apt install iputils-ping -y   # 如果镜像有 ping 命令可忽略
ping app2   # 成功解析并通信
  • 不需要使用 --link 或手动配置 /etc/hosts
  • 也可以使用 docker run --network mynet --name app3 ... 直接加入。

4. 将已有容器连接到网络

bash
# 将已运行的 app1 容器连接到 mynet(可以同时连接多个网络)
docker network connect mynet app1

# 断开连接
docker network disconnect mynet app1
  • 容器可以同时属于多个网络,实现网络隔离和桥接(例如一个容器同时对外提供服务、又能访问内部数据库网络)。

5. 端口映射(公开服务到宿主机)

端口映射使宿主机外的客户端能够访问容器内的服务。

bash
# 将宿主机 8080 端口映射到容器的 80 端口(TCP)
docker run -d -p 8080:80 nginx

# 指定协议(默认 TCP,可显式声明)
docker run -d -p 8080:80/tcp nginx

# UDP 映射
docker run -d -p 8080:80/udp nginx

# 同时映射 TCP 和 UDP
docker run -d -p 8080:80/tcp -p 8080:80/udp nginx

# 随机映射容器暴露的所有端口(主机端口从 32768 开始)
docker run -d -P nginx   # 注意是大写 -P
  • -p 可以多次使用,映射多个端口。
  • 查看映射情况:docker port <容器名>

6. 常用网络管理命令

命令说明
docker network ls列出所有网络
docker network inspect <网络名>查看网络详情(包括连接的容器)
docker network create <名称>创建自定义桥接网络
docker network rm <网络名>删除网络(需先断开所有容器)
docker network prune删除所有未被使用的网络
docker run --network <网络名>启动时指定网络
docker network connect <网络名> <容器名>将容器连接到网络
docker network disconnect <网络名> <容器名>断开容器与网络的连接

7. 最佳实践建议

  • 生产环境:为不同应用栈创建独立的自定义桥接网络,避免默认 bridge 网络的限制(无 DNS 解析)。
  • 微服务架构:使用自定义网络,通过容器名作为服务发现;跨主机场景可考虑 overlay 网络(需 Swarm 模式)或服务网格方案。
  • 端口映射:仅在需要对外暴露的服务上使用 -p;内部容器间通信无需映射端口,减少攻击面。
  • 宿主机网络:除非对性能有极致要求(且能解决端口冲突),一般不推荐使用 host 网络。

掌握 Docker 容器管理、数据持久化与网络基础,可以灵活构建容器间的通信拓扑,并为生产部署打下基础;多容器协同的编排方式见 Docker Compose

参考文献

相关文章