Docker容器启动命令最佳实践:MySQL、Redis、Nginx配置详解与避坑指南
1. 项目概述:为什么我们需要一份容器启动的“速查手册”?
干了这么多年开发和运维,我发现自己和身边同事的电脑里,总会有一个叫docker-commands.md或者常用命令.txt的文档。里面零零散散记录着各种启动 MySQL、Redis、Nginx 的命令和参数。每次新开项目或者换台机器部署,第一件事就是翻这个文档,复制粘贴,然后祈祷别出错。这其实反映了一个很普遍的需求:Docker 容器的启动命令,看似简单,实则藏着大量影响稳定性和性能的细节配置。
一个docker run命令,背后是端口映射、数据持久化、网络配置、资源限制、环境变量等一系列决策。对于常用的中间件和数据库,这些配置往往有“最佳实践”可循,但官方镜像的文档通常分散且默认配置不一定适合生产或开发环境。比如,MySQL 默认的字符集、Redis 的内存淘汰策略、Nginx 的配置文件挂载方式,这些细节没处理好,后期排查问题能让人抓狂。
所以,今天我就把自己压箱底的这份“常用容器启动命令及配置说明”整理出来,并附上我踩过坑之后总结的配置逻辑和避坑指南。这不仅仅是一个命令列表,更是一份解释“为什么这么配”的实操手册。无论你是刚接触 Docker 的新手,还是需要快速搭建一套标准开发环境的老手,这份指南都能让你避开我当年走过的弯路,直接上手稳定可靠的配置。
2. 核心思路:从“能用”到“好用”的配置哲学
在罗列具体命令之前,我们必须先统一思想:启动一个容器,目标不是让它“跑起来就行”,而是让它“在预期的状态下稳定、高效地运行”。这中间的区别,就体现在配置的精细程度上。我的配置思路主要围绕以下几个核心原则展开,这也是后续所有具体命令的指导思想。
2.1 持久化:数据是命根子,绝不能丢在容器里
容器本身是无状态的,停止或删除后,其内部产生的所有数据都会消失。对于数据库、文件服务这类应用,必须将数据目录挂载到宿主机(Host)的持久化存储上。
为什么必须这么做?想象一下,你花了几天时间在开发环境的 MySQL 里构造测试数据,某天因为清理磁盘空间,不小心把那个 MySQL 容器删了。如果数据在容器内部,一切就灰飞烟灭了。挂载到宿主机后,即使容器被销毁,数据文件依然安全。下次启动一个新容器,只需挂载同一个目录,数据就恢复了。
配置要点:
- 选择挂载类型:
-v或--mount。--mount语法更清晰、功能更明确(如指定挂载为只读),是新推荐的方式,但-v更简洁常用。本文为求直观,主要使用-v。 - 规划宿主机目录:建议在宿主机建立一个统一的目录来管理所有容器的数据,例如
/opt/docker-data/。下面再按容器名建立子目录,如/opt/docker-data/mysql、/opt/docker-data/redis。这样结构清晰,备份也方便。 - 注意目录权限:这是最常见的坑!容器内的进程通常以非 root 用户运行(为了安全)。如果你在宿主机用 root 创建的目录,容器进程可能没有写入权限,导致启动失败。解决方法:要么在启动前用
chmod更改宿主机目录权限(如777,但不安全),要么在 Dockerfile 或启动命令中做好用户映射,更推荐的是让容器在启动时自动初始化目录权限(有些官方镜像已处理)。
注意:在 Linux 宿主机上,如果遇到权限问题,可以先尝试在
docker run命令中加入-u参数指定用户,例如-u 1000:1000(使用 UID 和 GID),但这需要你知道容器内应用期望的用户。最稳妥的方式是参考官方镜像文档。
2.2 网络与端口:打通容器与外部世界的桥梁
默认情况下,容器运行在隔离的网络空间里。我们需要通过端口映射(Port Mapping)将容器内的服务端口暴露给宿主机乃至外部网络。
为什么需要精细配置?
- 避免端口冲突:宿主机上 3306、6379、80 这些常用端口可能已被占用。
- 安全考虑:生产环境中,数据库等服务可能只允许内部网络访问,不应将端口暴露到公网。
- 多环境一致性:开发、测试、生产环境可能使用不同的外部端口,但容器内部端口应保持固定。
配置要点:
- 格式:
-p <宿主机端口>:<容器内部端口>。例如-p 3307:3306表示将容器的 3306 端口映射到宿主机的 3307 端口。 - 绑定特定 IP:可以指定宿主机 IP,如
-p 127.0.0.1:3306:3306,这样 MySQL 只在本机可访问,更安全。 - 使用自定义网络:对于多容器应用(如 Web 应用 + 数据库),建议创建自定义的 Docker 网络(
docker network create mynet),然后使用--network mynet将容器加入同一网络。这样容器间可以通过容器名直接通信,无需通过宿主机 IP 和端口映射,更接近微服务架构。
2.3 环境变量:动态配置的钥匙
很多镜像,特别是数据库镜像,通过环境变量来接收初始配置,如 root 密码、数据库名等。这是配置容器行为最灵活的方式之一。
为什么用它?
- 分离配置与镜像:将敏感信息(如密码)或环境相关配置(如数据库名)从镜像中剥离,提高安全性和可移植性。
- 方便编排:在 Docker Compose 或 Kubernetes 中,可以轻松地管理大量环境变量。
配置要点:
- 格式:
-e KEY=VALUE或-e KEY=VALUE -e KEY2=VALUE2。也可以使用文件--env-file .env。 - 优先级:在 Docker Compose 中,环境变量定义在
environment部分,优先级高于.env文件。 - 敏感信息处理:切勿将密码等硬编码在命令行或 Dockerfile 中。对于生产环境,应使用 Docker Secret(Swarm 模式)或 Kubernetes Secrets 等更安全的机制。
2.4 资源限制:为容器戴上“紧箍咒”
默认情况下,容器可以使用宿主机的所有可用资源。这可能导致单个容器耗尽资源,影响其他容器或宿主机系统。
为什么需要限制?
- 稳定性:防止某个容器内存泄漏导致整个宿主机崩溃。
- 公平性:在共享的开发和测试环境中,确保每个项目或服务有公平的资源份额。
- 性能预估:为容量规划和性能测试提供依据。
配置要点:
- 内存:
-m 或 --memory限制最大使用内存,--memory-swap限制内存+交换分区总大小。通常--memory-swap设置为-m值的两倍,或者设置为-1(表示不限制交换分区,但可能有性能风险)。 - CPU:
--cpus限制可使用的 CPU 核心数(可以是小数,如1.5)。更精细的控制可以用--cpuset-cpus指定绑定的 CPU 核心编号。 - 实操心得:对于数据库等有状态服务,内存限制尤其重要。设置时需预留一部分给操作系统和其他进程。例如,在一个 8GB 内存的机器上,给 MySQL 容器设置
-m 4g是比较合理的起点。
3. 常用容器启动命令详解与配置解析
下面,我将针对几个最常用的中间件和数据库,给出经过实战检验的启动命令,并逐条解析关键参数背后的考量。你可以直接复制使用,但更重要的是理解每个参数的意义。
3.1 MySQL:关系型数据库的标杆
MySQL 的 Docker 镜像可能是使用最广泛的之一。它的配置相对复杂,涉及到字符集、排序规则、密码策略等。
基础启动命令:
docker run -d \ --name some-mysql \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORD=my-secret-pw \ -e MYSQL_DATABASE=myapp \ -e MYSQL_USER=appuser \ -e MYSQL_PASSWORD=apppassword \ -v /opt/docker-data/mysql:/var/lib/mysql \ --restart unless-stopped \ mysql:8.0 \ --character-set-server=utf8mb4 \ --collation-server=utf8mb4_unicode_ci \ --default-authentication-plugin=mysql_native_password参数拆解与避坑指南:
-e MYSQL_ROOT_PASSWORD=my-secret-pw:这是必须的环境变量,用于设置 root 用户的密码。请务必替换my-secret-pw为强密码。在测试环境,如果觉得麻烦,可以设置一个简单密码,但生产环境绝对不行。-e MYSQL_DATABASE=myapp:容器启动时自动创建的数据库名。这对于需要固定数据库名的应用(如 WordPress)非常方便。-e MYSQL_USER和-e MYSQL_PASSWORD:容器启动时自动创建的非 root 用户及其密码。强烈建议使用非 root 用户连接应用,遵循最小权限原则。-v /opt/docker-data/mysql:/var/lib/mysql:这是数据持久化的关键。将容器内 MySQL 的数据目录/var/lib/mysql挂载到宿主机的/opt/docker-data/mysql。首次启动时,如果宿主机目录为空,MySQL 会初始化数据文件到这个目录。之后容器销毁重建,只要挂载同一个目录,数据完好无损。--restart unless-stopped:重启策略。unless-stopped表示除非用户显式地执行docker stop停止容器,否则当容器退出或 Docker 守护进程重启时,容器都会自动重启。这对于需要长期运行的服务(如数据库)至关重要。mysql:8.0镜像标签后的参数:这些是传递给mysqld进程的额外命令行参数。--character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci:将服务器默认字符集设置为utf8mb4。这是 MySQL 中真正的 UTF-8 编码,支持存储所有 Unicode 字符(包括 Emoji)。这是中文互联网项目的标配,能避免很多“乱码”坑。早期用的utf8在 MySQL 中其实是阉割版,最多只支持 3 字节字符。--default-authentication-plugin=mysql_native_password:在 MySQL 8.0 早期版本中,默认的身份验证插件是caching_sha2_password,一些老的客户端驱动可能不支持。加上这个参数可以回退到旧的mysql_native_password插件,兼容性更好。注意:新版的驱动和客户端大多已支持新插件,如果你确定你的环境支持,可以去掉这个参数以使用更安全的新插件。
实操心得:权限问题处理如果你发现 MySQL 容器启动失败,查看日志 (
docker logs some-mysql) 显示/var/lib/mysql目录权限错误。可以尝试以下步骤:
- 确保宿主机目录存在:
sudo mkdir -p /opt/docker-data/mysql- 尝试先不挂载卷启动一个临时容器,让它初始化内部数据,然后复制出来:
然后修改宿主机目录权限:docker run -d --name temp-mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:8.0 docker cp temp-mysql:/var/lib/mysql /opt/docker-data/ docker stop temp-mysql && docker rm temp-mysqlsudo chmod -R 777 /opt/docker-data/mysql(仅用于快速解决问题,生产环境需更精细的权限控制)。- 最后,用上面带
-v的命令启动正式容器。
3.2 Redis:高性能键值存储
Redis 的配置相对简单,核心在于内存管理和持久化策略。
基础启动命令(带持久化):
docker run -d \ --name some-redis \ -p 6379:6379 \ -v /opt/docker-data/redis/data:/data \ -v /opt/docker-data/redis/conf:/usr/local/etc/redis \ --restart unless-stopped \ redis:7-alpine \ redis-server /usr/local/etc/redis/redis.conf \ --appendonly yes \ --requirepass "your_strong_password_here"参数拆解与避坑指南:
-v /opt/docker-data/redis/data:/data:挂载数据目录。Redis 的持久化文件(RDB 或 AOF)默认保存在/data目录。-v /opt/docker-data/redis/conf:/usr/local/etc/redis:挂载配置文件目录。这是强烈推荐的做法。Redis 的配置项很多,通过命令行参数传递既冗长又不便管理。更好的方式是使用自定义配置文件。- 首先,在宿主机创建配置目录:
mkdir -p /opt/docker-data/redis/conf - 然后,从官方镜像中复制一个默认配置文件出来修改:
docker run -d --name temp-redis redis:7-alpine docker cp temp-redis:/usr/local/etc/redis/redis.conf /opt/docker-data/redis/conf/ docker stop temp-redis && docker rm temp-redis - 接着,编辑
/opt/docker-data/redis/conf/redis.conf,修改你需要的参数,例如requirepass、maxmemory等。 - 最后,在启动命令中通过
redis-server /usr/local/etc/redis/redis.conf指定使用这个配置文件。
- 首先,在宿主机创建配置目录:
--appendonly yes:开启 AOF(Append Only File)持久化。AOF 会记录每一个写操作命令,并在重启时重新执行以恢复数据,相比 RDB(定时快照)数据安全性更高,通常与 RDB 结合使用。在配置文件中对应appendonly yes。--requirepass:设置 Redis 访问密码。生产环境必须设置!否则你的 Redis 相当于裸奔在公网上。密码应足够复杂。也可以在配置文件中设置requirepass项。redis:7-alpine:这里使用了 Alpine Linux 版本的镜像。Alpine 镜像体积非常小(通常只有官方镜像的 1/5 到 1/10),基于 musl libc 和 BusyBox。对于 Redis 这种单一进程服务,用 Alpine 版本能显著节省磁盘和内存空间。但需要注意,某些依赖 glibc 的特定工具或调试命令在 Alpine 上可能不可用。对于绝大多数使用场景,Alpine 版本是首选。
内存限制配置示例:如果需要在启动命令中直接限制内存并设置淘汰策略,可以这样写(但更推荐写入配置文件):
docker run -d \ --name some-redis-limited \ -p 6380:6379 \ -m 512m \ --memory-swap 512m \ redis:7-alpine \ redis-server \ --maxmemory 450mb \ --maxmemory-policy allkeys-lru \ --requirepass "your_password"-m 512m --memory-swap 512m:限制容器最多使用 512MB 物理内存,并且不使用交换分区(memory-swap等于memory表示禁用 swap)。这可以防止 Redis 使用 swap 导致性能急剧下降。--maxmemory 450mb:告诉 Redis 进程自身最多使用 450MB 内存。这个值应略小于 Docker 的内存限制,为 Redis 进程本身和其他开销留出空间。--maxmemory-policy allkeys-lru:当内存达到maxmemory时,Redis 的键淘汰策略。allkeys-lru表示在所有键中,淘汰最近最少使用的(LRU)。根据你的业务场景,也可以选择volatile-lru(只淘汰设定了过期时间的键中的 LRU)等策略。
3.3 Nginx:Web 服务器与反向代理
Nginx 容器通常需要挂载自定义配置、网站静态文件以及日志目录。
基础启动命令(作为静态文件服务器):
docker run -d \ --name some-nginx \ -p 80:80 \ -p 443:443 \ -v /path/to/your/website:/usr/share/nginx/html:ro \ -v /opt/docker-data/nginx/conf.d:/etc/nginx/conf.d:ro \ -v /opt/docker-data/nginx/logs:/var/log/nginx \ --restart unless-stopped \ nginx:alpine参数拆解与避坑指南:
-v /path/to/your/website:/usr/share/nginx/html:ro:将你的网站静态文件目录挂载到容器内 Nginx 的默认站点根目录。:ro表示“只读”(read-only),这是一个重要的安全实践,防止容器内的进程意外或恶意修改你的源文件。-v /opt/docker-data/nginx/conf.d:/etc/nginx/conf.d:ro:挂载自定义配置文件目录。Nginx 主配置文件是/etc/nginx/nginx.conf,但它通常会包含/etc/nginx/conf.d/目录下的所有.conf文件。我们将宿主机的目录挂载到这里,就可以灵活地管理多个站点的配置,而无需进入容器或重建镜像。- 在宿主机
/opt/docker-data/nginx/conf.d/下创建一个文件,例如my-site.conf:server { listen 80; server_name localhost; location / { root /usr/share/nginx/html; index index.html index.htm; } # 可以在这里添加其他配置,如反向代理、gzip等 } - 重启容器 (
docker restart some-nginx) 或使用docker exec some-nginx nginx -s reload重载配置即可生效。
- 在宿主机
-v /opt/docker-data/nginx/logs:/var/log/nginx:挂载日志目录。这样 Nginx 的访问日志和错误日志就会直接写在宿主机上,方便用tail、grep等工具查看,也便于用 ELK 等日志系统收集。注意这里没有加:ro,因为 Nginx 进程需要向这个目录写入日志。nginx:alpine:同样,对于 Nginx 这种轻量级服务,Alpine 版本是绝佳选择,镜像体积小,启动快。
作为反向代理的配置示例:假设你有一个运行在localhost:3000的 Node.js 应用,想用 Nginx 做反向代理并处理静态文件。 在宿主机/opt/docker-data/nginx/conf.d/下创建reverse-proxy.conf:
server { listen 80; server_name your-domain.com; # 或 localhost 用于测试 # 静态文件服务 location /static/ { alias /usr/share/nginx/html/static/; expires 30d; # 缓存30天 } # 反向代理到后端应用 location / { proxy_pass http://host.docker.internal:3000; # 关键!指向宿主机服务 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }这里的关键点是proxy_pass http://host.docker.internal:3000;。在 Docker for Mac/Windows 或较新版本的 Docker Desktop 中,host.docker.internal是一个特殊的主机名,解析为宿主机的 IP 地址。在 Linux 宿主机上,你可能需要使用宿主机的实际 IP 地址(如172.17.0.1,这是 Docker 默认网桥docker0的网关地址),或者使用--network=host模式运行容器(但这会失去部分网络隔离性)。
3.4 PostgreSQL:另一个强大的开源数据库
PostgreSQL 的配置思路与 MySQL 类似,但环境变量和持久化路径有所不同。
基础启动命令:
docker run -d \ --name some-postgres \ -p 5432:5432 \ -e POSTGRES_PASSWORD=mysecretpassword \ -e POSTGRES_USER=myuser \ -e POSTGRES_DB=mydatabase \ -v /opt/docker-data/postgresql/data:/var/lib/postgresql/data \ -v /opt/docker-data/postgresql/init.sql:/docker-entrypoint-initdb.d/init.sql \ --restart unless-stopped \ postgres:15-alpine \ -c shared_buffers=256MB \ -c max_connections=200参数拆解与避坑指南:
环境变量:
POSTGRES_PASSWORD:必须,设置超级用户postgres的密码。POSTGRES_USER和POSTGRES_DB:可选。如果设置了,容器启动时会自动创建指定用户和数据库,并且该用户将成为该数据库的所有者。这比手动创建方便很多。
-v /opt/docker-data/postgresql/data:/var/lib/postgresql/data:标准的数据持久化挂载点。-v /opt/docker-data/postgresql/init.sql:/docker-entrypoint-initdb.d/init.sql:这是一个非常实用的技巧!官方 PostgreSQL 镜像会在首次初始化数据库时(即数据目录为空时),自动执行/docker-entrypoint-initdb.d/目录下的所有.sh、.sql、.sql.gz文件。我们可以利用这个机制,在宿主机上准备好初始化 SQL 脚本(如创建表、导入基础数据、创建扩展等),挂载进去,容器第一次启动时就会自动执行。注意:这个机制只在数据目录为空(首次创建)时运行一次。postgres:15-alpine镜像标签后的参数:这些以-c开头的参数是直接传递给postgres进程的运行时配置,相当于修改postgresql.conf文件。例如:-c shared_buffers=256MB:设置数据库使用的共享内存缓冲区大小。通常建议设置为系统内存的 25%,但容器内需考虑限制值。-c max_connections=200:设置最大连接数。
注意:对于生产环境,更推荐将复杂的配置写入一个自定义的
postgresql.conf文件,然后通过-v挂载到容器内的/etc/postgresql/postgresql.conf,并在启动命令中通过-c config_file=/etc/postgresql/postgresql.conf指定。命令行-c参数适合覆盖少量配置。
4. 进阶配置与编排:从单容器到多容器应用
当你需要同时启动多个有依赖关系的容器(例如一个 Web 应用容器和一个数据库容器)时,手动使用docker run会变得繁琐且难以管理。这时,Docker Compose 是更优雅的解决方案。它使用一个 YAML 文件(docker-compose.yml)来定义和运行多容器应用。
示例:一个简单的 WordPress 网站(包含 WordPress 和 MySQL)
创建docker-compose.yml文件:
version: '3.8' services: db: image: mysql:8.0 container_name: wp_mysql restart: unless-stopped environment: MYSQL_ROOT_PASSWORD: some_root_password MYSQL_DATABASE: wordpress MYSQL_USER: wordpress MYSQL_PASSWORD: wordpress_password volumes: - ./mysql_data:/var/lib/mysql - ./mysql_conf:/etc/mysql/conf.d networks: - wp_network # 资源限制示例 deploy: resources: limits: memory: 512M cpus: '0.5' wordpress: image: wordpress:latest container_name: wp_app restart: unless-stopped ports: - "8080:80" environment: WORDPRESS_DB_HOST: db:3306 WORDPRESS_DB_USER: wordpress WORDPRESS_DB_PASSWORD: wordpress_password WORDPRESS_DB_NAME: wordpress volumes: - ./wp_html:/var/www/html networks: - wp_network depends_on: - db networks: wp_network: driver: bridgeCompose 文件关键点解析:
services:定义了两个服务db和wordpress。networks:定义了一个自定义网络wp_network,两个服务都加入其中。在同一个自定义网络下的容器,可以直接通过服务名(这里是db)进行通信,无需知道 IP 地址。wordpress容器中WORDPRESS_DB_HOST: db:3306正是利用了这一点。volumes:数据卷定义。这里使用了相对路径./mysql_data,会在docker-compose.yml文件所在目录创建文件夹。管理起来比绝对路径更灵活。depends_on:指定依赖关系。Docker Compose 会先启动db服务,然后再启动wordpress服务。但请注意,这只控制启动顺序,并不保证db服务内的 MySQL 进程已经完全启动并准备好接受连接。对于这种需求,需要更复杂的健康检查配置。deploy.resources.limits:在 Compose 文件中可以方便地定义资源限制(注意:deploy部分通常用于 Docker Swarm 模式,但在docker-compose up时,某些版本的 Docker Desktop 也支持部分属性,如资源限制。纯 Docker Engine 环境下,建议使用mem_limit,cpus等旧属性,或参考最新文档)。
操作命令:
- 启动所有服务:
docker-compose up -d - 停止并移除所有服务:
docker-compose down - 查看日志:
docker-compose logs -f - 在项目目录下,这些命令会自动识别
docker-compose.yml文件并作用于其中定义的所有服务,管理效率远超手动操作多个docker run命令。
5. 常见问题排查与运维技巧实录
即使配置再仔细,在实际操作中依然会遇到各种问题。下面是我总结的几个高频问题及其排查思路。
5.1 容器启动失败,如何查看日志?
这是第一步,也是最重要的一步。
# 查看容器最近日志 docker logs <容器名或容器ID> # 持续跟踪日志输出(类似 tail -f) docker logs -f <容器名或容器ID> # 查看容器从启动到现在的完整日志 docker logs --since 30m <容器名或容器ID> # 查看最近30分钟的日志如果容器启动后立刻退出,可以尝试在前台运行以查看输出:
docker run --rm -it --name test-mysql -e MYSQL_ROOT_PASSWORD=123 mysql:8.0--rm表示容器退出后自动删除,-it表示交互式终端,这样任何启动错误都会直接打印在终端上。
5.2 如何进入正在运行的容器内部?
有时需要进入容器检查文件、执行命令或调试。
# 最常用的方式,启动一个交互式 bash 会话(容器内必须有 bash) docker exec -it <容器名或容器ID> /bin/bash # 如果容器是 Alpine 基础镜像,可能没有 bash,用 sh docker exec -it <容器名或容器ID> /bin/sh # 直接在容器内执行一条命令并退出 docker exec <容器名或容器ID> ls -la /var/lib/mysql5.3 端口被占用或冲突怎么办?
错误信息通常类似Bind for 0.0.0.0:3306 failed: port is already allocated。
- 排查:在宿主机上使用
netstat -tulpn | grep :3306(Linux)或lsof -i :3306(Mac)查看是哪个进程占用了端口。 - 解决:
- 停止占用端口的无关进程。
- 或者,修改你的
docker run命令,映射到另一个宿主机端口,例如-p 3307:3306。
5.4 如何备份和恢复容器数据?
数据在宿主机挂载的目录里,所以备份其实就是备份那个目录。
- 备份:直接打包宿主机上的数据目录即可。例如,备份 MySQL 数据:
tar -czf mysql_backup_$(date +%Y%m%d).tar.gz /opt/docker-data/mysql/ - 恢复:
- 停止对应的容器:
docker stop some-mysql - 备份当前数据(以防万一)。
- 清空或重命名原数据目录:
mv /opt/docker-data/mysql /opt/docker-data/mysql_old - 解压备份文件到原路径:
tar -xzf mysql_backup_20231027.tar.gz -C /opt/docker-data/ - 确保目录权限正确(参考前面的权限问题处理)。
- 重新启动容器:
docker start some-mysql
- 停止对应的容器:
5.5 容器占用了太多磁盘空间,如何清理?
Docker 占用的空间主要包括:镜像、容器、数据卷、构建缓存。
# 查看 Docker 磁盘使用概况 docker system df # 删除所有已停止的容器、未被任何容器引用的网络、悬空镜像(未被标记且未被任何容器引用的镜像)和构建缓存 docker system prune # 警告:此命令会删除所有未被使用的镜像、容器、网络和数据卷,非常彻底! docker system prune -a --volumes谨慎使用prune -a,尤其是--volumes,它会删除未被容器引用的数据卷,可能导致数据丢失。在执行前,务必用docker volume ls确认哪些卷是重要的。
5.6 如何更新容器到新版本的镜像?
对于无状态服务,更新相对简单:
- 拉取新镜像:
docker pull nginx:latest - 停止并删除旧容器:
docker stop some-nginx && docker rm some-nginx - 用新镜像和相同的配置(最好保存为脚本或 Compose 文件)重新运行
docker run ...命令。
对于有状态服务(如数据库),更新需要格外小心:
- 完整备份数据。
- 查阅官方镜像的更新日志,确认版本间是否有不兼容的变更。
- 通常做法是:用新镜像启动一个临时容器,将旧数据卷挂载进去,执行升级脚本(很多官方镜像会自动执行)。测试无误后,再切换流量或替换旧容器。
- 对于 MySQL/PostgreSQL 等,大版本升级(如 5.7 到 8.0)往往不是简单的替换镜像就能完成的,需要遵循官方的升级指南。
这份“速查手册”和背后的逻辑,是我多年使用 Docker 部署常用服务积累下来的经验结晶。从简单的单命令启动,到考虑持久化、网络、资源限制的完整配置,再到使用 Docker Compose 编排多服务应用,最后是遇到问题时的排查思路,基本覆盖了日常开发和测试环境的需求。记住,最好的配置是那些你理解其每一条含义的配置。希望这份详细的解析能帮你不仅“复制粘贴”,更能“心中有数”,搭建出稳定、可控的容器化服务环境。
