ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Docker实战指南:从容器核心概念到MySQL、Redis与Compose部署全流程

Docker实战指南:从容器核心概念到MySQL、Redis与Compose部署全流程 最近总被人问同一类问题同事发过来的镜像怎么跑起来MySQL 怎么用 Docker 装才不容易丢数据Redis 主从怎么配还有人在 Windows 上报错提示virtualization support not detected一搜一大堆结果照着敲完还是起不来。聊到最后我基本都会回一句先把 Docker 的使用流程打通剩下的事都好说。这篇文章就按我平时实际使用的路线来写从安装、核心概念、常用命令到 MySQL 8.0、Redis 主从、GitLab、Docker Compose、镜像构建、青龙面板部署一路把坑标出来你会踩到的和容易忽略的我都尽量写进去。无论你是刚接触容器的新手还是已经用了 Docker 但经常在细节上翻车的开发/运维这篇文章应该都能帮上忙。1. 先把容器这事想明白再动手不迟1.1 容器到底解决了什么问题你大概率听过这么一句话“在我机器上是好的呀。”这句话背后其实是环境不一致的问题操作系统不同、软件版本不同、配置文件不同、依赖库不同代码跑起来的结果就会千奇百怪。Docker 把应用和它依赖的运行环境一起打成一个“镜像”启动后就是一个隔离的“容器”不管底下是 Windows、Ubuntu 还是 CentOS容器里面看到的环境都一样。我习惯拿“货柜”来类比。以前搬家东西散着装锅碗瓢盆、衣服书籍混在一起到了新家还要重新整理。现在你把所有东西分类装进标准集装箱集装箱本身就是完整的单元搬运到哪都长一个样子。Docker 镜像就是那个箱子容器就是被搬运到新家、实际使用的那个箱子。你不需要关心集装箱用了什么钢材、什么轮子你只需要把东西按规矩放进去它就能被可靠地复现。1.2 Docker 和虚拟机的本质差别虚拟机是在物理机上虚拟出一套完整的硬件再在上面跑一个完整的操作系统所以它启动慢、占资源多。而容器直接复用宿主机的操作系统内核只做进程级别的隔离启动快、占资源少。简单说虚拟机里跑应用要先启动一台“假电脑”容器里跑应用只是启动一个“被关在单间里的进程”。这带来一个实操上的直接感受一个 MySQL 容器启动只要一两秒而一台虚拟机光开机就要好几分钟。所以在本地开发、CI/CD 构建、快速部署这类场景里容器几乎成了默认选择。1.3 哪些人、哪些场景适合用 Docker开发环境统一新同事入职不再花两天装环境给份 docker-compose 文件一条命令跑起来。服务端部署同一个镜像推送到测试机和生产机行为一致少了“环境差异”这个变量。自建服务GitLab、MySQL、Redis、Nginx、青龙面板这类服务用容器维护起来清爽很多。工具链隔离有些工具要 Python 3.8有些要 Python 3.11用容器隔离互不干扰。但也别把所有东西都塞进容器。有状态的服务数据库不是不能容器化而是对数据持久化、网络配置和备份策略有要求。这部分是重点后面会专门讲。2. 先迈过安装这道坎从 Windows 到 Ubuntu2.1 Windows 环境安装 Docker DesktopWindows 上现在最省事的方案就是安装 Docker Desktop。它自带图形管理界面可以查看容器、镜像、日志也可以直接跑常用命令对新手非常友好。安装之前请先确认两件事CPU 要支持虚拟化并且已经在 BIOS 里开启。系统最好更新到 Windows 10/11 较新的版本并且安装好 WSL2。第一步以管理员身份打开 PowerShell执行wsl --install这个命令会安装 WSL 和默认的 Linux 发行版。安装完重启电脑。如果系统较新这一步基本上能帮你搞定 WSL2 内核。第二步下载 Docker Desktop 安装包官方地址是https://www.docker.com/products/docker-desktop/。下载下来双击安装一路下一步即可。第三步安装完成后启动 Docker Desktop在设置里确保使用 WSL 2 based engine默认就是。如果启动时报错Docker Desktop failed to start because virtualization support wasnt detected不要慌按下面的思路排查进 BIOS把 Intel VT-x / AMD-V 开启。不同主板位置不一样搜索栏里搜“Virtualization”或“SVM Mode”。确认 Windows 的“适用于 Linux 的 Windows 子系统”功能已开启。在 PowerShell 执行wsl --status查看状态。执行bcdedit /set hypervisorlaunchtype auto管理员权限后重启确保 Hyper-V 的 hypervisor 正常加载。我见过很多次的情况是核心虚拟化功能没开全Windows 功能列表里“虚拟机平台”和“Windows 虚拟机监控程序平台”没勾选。执行开始菜单搜“启用或关闭 Windows 功能”把这两个都勾上重启后启动 Docker Desktop 就正常了。2.2 macOS 环境安装 Docker DesktopmacOS 用户直接去官网下 Docker Desktop for Mac 安装即可。注意区分 Intel 芯片和 Apple Silicon 芯片的版本M 系列芯片选对应的 Arm 版本。安装后也需要给 Docker 授权第一次启动会要求输入系统密码。2.3 Ubuntu 上安装 Docker Engine服务器或开发机上用 Ubuntu 比较多我一般用一个脚本搞定curl -fsSL https://get.docker.com | sh sudo systemctl enable --now docker这个脚本会配置官方源、安装 Docker Engine、containerd 和 Docker Compose 插件基本不需要手动处理依赖。装完后验证一下docker version docker compose version如果不想用脚本也可以手动装。核心步骤是sudo apt update sudo apt install -y ca-certificates curl sudo install -m 0755 -d /etc/apt/keyrings sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc sudo chmod ar /etc/apt/keyrings/docker.asc echo \ deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \ $(. /etc/os-release echo $VERSION_CODENAME) stable | \ sudo tee /etc/apt/sources.list.d/docker.list /dev/null sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin装完后记得把当前用户加入 docker 组避免每次都要 sudosudo usermod -aG docker $USER newgrp docker注意加入 docker 组后用户对 docker socket 有完全控制权权限等同于 root仅限于自己信任的开发机或个人服务器。生产环境请自行评估安全策略。2.4 关于龙芯、ARM 等特殊平台的注意点龙芯等平台不能直接用官方 x86 包。这类平台要么有厂商自己维护的 Docker 分支要么需要从源码编译。更实际的做法是优先用官方仓库里支持的架构标签搜索镜像时加--filter platform参数。x86 的镜像不能直接跑在 ARM 上要么找对应架构的镜像要么用 Docker Buildx 做跨平台构建。我自己在 ARM 开发板上跑过测试优先选择arm64v8系列的镜像比硬转 x86 镜像稳得多。2.5 安装后的自检装完别急着拉镜像先跑一个最简单的容器docker run --rm hello-world看到 “Hello from Docker!” 说明安装成功。然后看下docker info里面会显示 Docker 的根目录、存储驱动、镜像数量等信息。这条命令基本能反映 Docker 环境的健康程度。3. 每天都要用的核心概念与常用命令3.1 镜像、容器、仓库三个词不能混镜像是一个只读的模板由一层层文件系统组成。容器是镜像运行后产生的实例可以启动、停止、删除。仓库是存放镜像的地方Docker Hub 是最大的公共仓库企业里还会搭私有仓库Harbor、Registry。打一个比方镜像像程序安装包容器像运行中的程序仓库像应用商店。安装包本身不能跑只有启动了才能用。3.2 镜像管理命令docker pull nginx:latest # 拉取镜像 docker images # 查看本地镜像 docker rmi nginx # 删除镜像 docker tag nginx:latest mynginx:v1 # 打标签 docker inspect nginx # 查看镜像详情docker inspect是排查问题时的利器可以看到环境变量、挂载卷、网络模式等一切元信息。遇到容器起不来先 inspect别急着猜。3.3 容器生命周期命令创建并启动容器用的是docker run参数组合非常多。写一个 Nginx 示例docker run -d --name web -p 8080:80 -v /www:/usr/share/nginx/html nginx这里-d是后台运行--name给容器起名-p映射端口-v挂载目录。启动后浏览器访问本机http://localhost:8080就能看到 Nginx 默认页面。其他常用命令docker ps # 查看运行中的容器 docker ps -a # 查看所有容器包括已停止 docker start web # 启动 docker stop web # 停止 docker restart web # 重启 docker rm -f web # 强制删除 docker logs -f web # 跟踪日志 docker exec -it web bash # 进入容器交互终端docker exec -it是在容器里执行命令的入口进容器排查文件或看配置很有用。注意容器里面默认没有 vi/vim需要现装或者直接在外层把配置改好再挂载进去我基本都走后一种方案。3.4 端口、数据卷、网络容器三大连接件端口映射解决“从外面怎么访问容器”的问题。宿主机端口和容器端口一一对应格式是宿主机端口:容器端口。比如-p 3306:3306含义是把宿主机的 3306 映射到容器的 3306。如果宿主机端口被占用可以换成-p 3307:3306。数据卷解决“容器删了数据怎么办”的问题。容器删除后文件系统默认也会消失所以数据库这类有状态应用必须持久化。两种做法docker run -v /my/data:/var/lib/mysql mysql:8.0 docker run -v mysql_data:/var/lib/mysql mysql:8.0第一种是绑定挂载宿主机目录文件路径直观第二种是命名卷由 Docker 管理位置迁移更方便。用docker volume ls可以查看命名卷。网络解决“容器之间怎么互相访问”的问题。同属一个自定义网络的容器可以直接用容器名当主机名访问。例如 MySQL 容器名为db应用容器里连接jdbc:mysql://db:3306就能通。自定义网络用起来很简单docker network create mynet docker network connect mynet web4. 实战一安装 MySQL 8.0 并让业务跑起来4.1 拉取镜像和准备目录MySQL 用 Docker 跑最需要注意的不是安装而是数据安全和时区字符集。先创建本地目录把数据和配置分离mkdir -p /data/mysql/{data,conf}然后拉取镜像docker pull mysql:8.0我一般不用latest标签因为 MySQL 大版本升级后行为变化很大。生产环境老老实实锁定小版本例如mysql:8.0.32。4.2 启动容器的正确姿势启动命令docker run -d \ --name mysql8 \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORDyourpassword \ -e TZAsia/Shanghai \ -v /data/mysql/data:/var/lib/mysql \ -v /data/mysql/conf:/etc/mysql/conf.d \ --restart always \ mysql:8.0解释一下几个关键点MYSQL_ROOT_PASSWORD是首次初始化时设置 root 密码的环境变量。首次启动时容器会根据这个变量初始化数据库后面再改则不生效。TZAsia/Shanghai设置时区避免数据库时间和系统时间差 8 小时。--restart always让容器退出后自动重启适合开机自启和服务常驻。启动后等几秒因为首次初始化需要时间。看日志确认就行docker logs -f mysql8看到ready for connections就说明 MySQL 起来了。4.3 客户端连接与常见错误连 MySQL 前先确认容器里的 MySQL 版本和端口docker exec -it mysql8 mysql -uroot -p进入后执行SELECT VERSION(); SHOW VARIABLES LIKE character_set_server;如果发现自己表里的中文乱码十有八九是字符集没对齐。MySQL 8.0 默认utf8mb4但有些旧客户端、旧库迁移过来可能仍是latin1。可以在挂载的配置文件/data/mysql/conf/my.cnf里写[mysqld] character-set-serverutf8mb4 collation-serverutf8mb4_unicode_ci改完docker restart mysql8。还有一个高概率报错Access denied for user root...。如果你需要让应用远程连接 root建议不要开 root 远程而是新建一个业务账号CREATE USER app% IDENTIFIED BY apppass; GRANT ALL PRIVILEGES ON *.* TO app%; FLUSH PRIVILEGES;这里%表示允许任意 IP实际使用请根据网络环境收紧为具体网段。4.4 数据备份与恢复容器里的数据库备份要基于容器做不要直接在宿主机拷贝数据目录。推荐用mysqldumpdocker exec mysql8 sh -c exec mysqldump -uroot -p$MYSQL_ROOT_PASSWORD --all-databases /data/backup/all.sql恢复docker exec -i mysql8 sh -c exec mysql -uroot -p$MYSQL_ROOT_PASSWORD /data/backup/all.sql定时备份可以写个 cron 脚本每天凌晨跑一次。我自己习惯保留最近 7 天的备份文件再多就清理掉。5. 实战二Redis 单机与主从部署5.1 快速起一个单机 RedisRedis 是一个内存型数据库容器化非常简单docker run -d \ --name redis \ -p 6379:6379 \ -v /data/redis/data:/data \ --restart always \ redis:7.0这里没有设置密码。如果需要密码加--requirepass参数或用配置文件docker run -d \ --name redis \ -p 6379:6379 \ -v /data/redis/data:/data \ -v /data/redis/redis.conf:/etc/redis/redis.conf \ redis:7.0 redis-server /etc/redis/redis.conf配置文件里可以写requirepass yourRedisPass appendonly yes appendfilename appendonly.aofappendonly yes开启 AOF 持久化这样 Redis 重启后数据不容易丢。纯做缓存的场景可以不开有业务数据的要求必须开。5.2 主从复制三分钟搭一套主从复制是 Redis 高可用的基础。原理很简单主节点master负责写从节点replica负责同步主节点的数据实现读写分离和数据冗余。先启动主节点docker network create redis-net docker run -d \ --name redis-master \ --network redis-net \ -p 6379:6379 \ -v /data/redis/master:/data \ redis:7.0 \ redis-server --appendonly yes --requirepass masterpass然后启动两个从节点docker run -d \ --name redis-slave1 \ --network redis-net \ -p 6380:6379 \ -v /data/redis/slave1:/data \ redis:7.0 \ redis-server --appendonly yes --replicaof redis-master 6379 --masterauth masterpass docker run -d \ --name redis-slave2 \ --network redis-net \ -p 6381:6379 \ -v /data/redis/slave2:/data \ redis:7.0 \ redis-server --appendonly yes --replicaof redis-master 6379 --masterauth masterpass这里最关键的是--replicaof redis-master 6379。由于两个容器在自定义网络redis-net里直接使用容器名redis-master作为宿主机名Docker 内置 DNS 会自动解析到对应 IP。如果不用自定义网络从节点只能填主节点在宿主机上的 IP一旦 IP 变化就要重新配置麻烦得很。验证主从是否成功docker exec -it redis-slave1 redis-cli -a masterpass info replication看到role:slave且master_link_status:up就正常了。5.3 主从部署的坑一定要配置--masterauth。即使主节点设了密码从节点同步时也要认证否则日志里会出现MASTER aborted replication with an error: NOAUTH Authentication required。主从不是自动故障转移。主节点挂了业务不会自动切换到从节点。要自动切换得再上哨兵Sentinel或 Redis Cluster那是另一套复杂度。从节点默认只读。info replication里slave_read_only:1不用担心从节点被写坏。6. 实战三用 Docker 部署 GitLab6.1 GitLab 容器化之后的资源门槛GitLab 是一个功能完整的 DevOps 平台正因如此它比较吃资源。官方推荐至少 4GB 内存我自己在 2GB 内存的机器上跑到跑起来但一有构建任务就卡成 PPT。所以你要用 GitLab先确认机器内存不低于 4GB磁盘留个 20GB 以上否则就别浪费时间了。6.2 启动 GitLab 容器GitLab 用 Docker 部署有一个好处升级方便备份也简单。官方镜像名是gitlab/gitlab-ce社区版免费。先建目录mkdir -p /data/gitlab/{config,logs,data}然后启动docker run -d \ --name gitlab \ -p 8083:80 \ -p 8022:22 \ -e GITLAB_ROOT_PASSWORDYourRootPass123 \ -v /data/gitlab/config:/etc/gitlab \ -v /data/gitlab/logs:/var/log/gitlab \ -v /data/gitlab/data:/var/opt/gitlab \ --restart always \ gitlab/gitlab-ce:16.8.0-ce.0这里把宿主机的 8083 映射到容器内的 80。因为宿主机 80 端口很可能被其他 Web 服务占用我特意选了 8083。访问地址就是http://服务器IP:8083初始化大概需要几分钟可以用docker logs -f gitlab看进度。6.3 初始化配置和 root 密码第一次启动时如果没设置GITLAB_ROOT_PASSWORDGitLab 会在/etc/gitlab/initial_root_password生成随机密码。我在上面的命令里直接指定了 root 密码省去再进容器找密码的麻烦。有一点要注意GitLab 会基于访问地址生成本项目的仓库地址。如果你用http://IP:8083访问那么项目 clone 地址也会带 8083 端口。如果你后面打算用域名 HTTPS 访问需要在/data/gitlab/config/gitlab.rb里修改external_url http://gitlab.example.com修改后执行docker exec gitlab gitlab-ctl reconfigure docker restart gitlab6.4 备份和恢复GitLab 自带完整备份命令docker exec -t gitlab gitlab-backup create备份文件会生成在/var/opt/gitlab/backups也就是挂载到宿主机/data/gitlab/data/backups目录。恢复时先停止相关服务再恢复步骤稍多生产环境用 GitLab 官方文档为准。只备份代码库的话直接跑 git clone 到本地仓库里也不失为一种简单的保险策略。7. 用 Docker Compose 编排多容器服务7.1 为什么需要 Docker Compose当服务多起来后一条条docker run命令不但记不住还特别容易漏参数。Docker Compose 可以把多个容器的配置写在一个docker-compose.yml文件里一条命令全部拉起是本地开发和中小项目部署的首选。一个典型场景博客系统由 Nginx 前端、应用后端、MySQL 数据库组成用 Compose 管理三个服务比手动敲命令可靠得多。7.2 一个 MySQL Redis 后端的 Compose 示例version: 3.8 services: mysql: image: mysql:8.0 container_name: app-mysql restart: always environment: MYSQL_ROOT_PASSWORD: rootpass MYSQL_DATABASE: appdb MYSQL_USER: app MYSQL_PASSWORD: apppass TZ: Asia/Shanghai volumes: - mysql_data:/var/lib/mysql ports: - 3306:3306 networks: - app-net redis: image: redis:7.0 container_name: app-redis restart: always command: redis-server --appendonly yes --requirepass redispass volumes: - redis_data:/data ports: - 6379:6379 networks: - app-net backend: image: myapp-backend:latest container_name: app-backend restart: always environment: DB_HOST: mysql DB_PORT: 3306 DB_USER: app DB_PASSWORD: apppass REDIS_HOST: redis REDIS_PASSWORD: redispass ports: - 8080:8080 depends_on: - mysql - redis networks: - app-net volumes: mysql_data: redis_data: networks: app-net: driver: bridge看到没有后端服务连接数据库时DB_HOST直接写服务名mysql连接 Redis 就写redis。Compose 会自动创建app-net网络容器之间通过服务名互相通信不再关心 IP 变化。7.3 Compose 的常用命令docker compose up -d # 按配置启动全部服务 docker compose ps # 查看服务状态 docker compose logs -f # 跟踪全部服务日志 docker compose logs backend # 只看某个服务日志 docker compose down # 停止并删除容器 docker compose down -v # 连数据卷一起删慎用 docker compose pull # 拉取最新镜像 docker compose restart backend # 重启某个服务down -v会把命名卷一起删掉意味着 MySQL、Redis 里的数据全没。这句话我每次必须在文章里单独标一次因为很多第一次用的人误操作过。7.4 环境变量和 .env 文件Compose 支持.env文件统一管理变量。在docker-compose.yml同目录下创建.envMYSQL_ROOT_PASSWORDrootpass MYSQL_DATABASEappdb然后在 yml 里引用environment: MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}这样密码、端口这类容易变化的信息不用直接写在 yml 里也更方便在不同环境之间切换比如开发环境一份.env.development生产环境一份.env.production。8. 镜像构建与 IDEA 打包 Docker 镜像8.1 写一个最小 Dockerfile镜像不只是从仓库拉还得自己构建。比如你写了一个 Spring Boot 项目想把它打成镜像发布就需要一个 Dockerfile。先看最小示例# 基础镜像 FROM openjdk:17-jdk-slim # 工作目录 WORKDIR /app # 把构建好的 jar 复制进去 COPY target/app.jar /app/app.jar # 暴露端口 EXPOSE 8080 # 启动命令 ENTRYPOINT [java, -jar, /app/app.jar]构建docker build -t myapp:1.0 .-t是镜像名和标签最后的.表示构建上下文目录。构建完成后docker run -p 8080:8080 myapp:1.0就能跑。8.2 多阶段构建把镜像体积压下来我曾经见过一个部署包好几百 MB里面一半是编译工具和源码。多阶段构建可以把编译环境和运行环境分开最终镜像只保留运行所需内容。Java 项目的典型例子# 第一阶段编译 FROM maven:3.8-openjdk-17 AS builder WORKDIR /app COPY pom.xml . RUN mvn dependency:go-offline COPY src ./src RUN mvn clean package -DskipTests # 第二阶段运行 FROM openjdk:17-jdk-slim WORKDIR /app COPY --frombuilder /app/target/app.jar app.jar EXPOSE 8080 ENTRYPOINT [java, -jar, /app/app.jar]最终镜像只有 JDK 环境加一个 jar干净很多。前端项目也一样先 Node 环境跑npm build最后只把构建产物放到 Nginx 镜像里。FROM node:18 AS build WORKDIR /app COPY package*.json ./ RUN npm install COPY . . RUN npm run build FROM nginx:alpine COPY --frombuild /app/dist /usr/share/nginx/html EXPOSE 808.3 IDEA 里集成 Docker 插件IntelliJ IDEA 支持直接操作 Docker平时开发调试很方便。打开 Settings - Plugins安装 Docker 插件然后在 Settings - Build, Execution, Deployment - Docker 里配置连接Windows 上选 Docker Desktop 的 socketLinux 上也可以填unix:///var/run/docker.sock。配置好后右侧会多出 Docker 面板能看到本地镜像、容器、网络日志也直接在面板里输出。想把项目打成镜像直接在 Service 面板里右键 Dockerfile选择 Build Image不用再切到命令行敲docker build。对 Spring Boot 项目更顺滑的做法是集成dockerfile-maven-plugin。在pom.xml里加插件然后执行mvn package dockerfile:build它会自动构建镜像并推到本地仓库。这个流程一旦跑通改代码、打包、起容器、测试循环效率会明显提升。8.4 镜像构建的避坑经验注意.dockerignore。和.gitignore类似把target/、.git/、node_modules/这些目录排除掉既加快构建又避免把本地文件传染给镜像。构建上下文不要放无关大文件。docker build会把上下文目录整个发给 Docker daemon目录越大构建越慢。基础镜像尽量选 slim 或 alpine 版本减少攻击面和磁盘占用。镜像标签不要都用latest。发布版本建议用日期或流水号例如myapp:20250512-01方便回滚。9. 青龙面板的 Docker 部署与依赖管理9.1 青龙面板是什么青龙面板是一个定时任务管理面板可以集中管理脚本任务、查看日志、配置环境变量。社区很多人拿它跑各类自动化脚本我自己主要把它当定时任务平台用管理一些重复性高的运维和数据处理脚本。Docker 部署青龙非常简单mkdir -p /data/qinglong docker run -d \ --name qinglong \ -p 5700:5700 \ -v /data/qinglong/config:/ql/config \ -v /data/qinglong/logs:/ql/log \ -v /data/qinglong/data:/ql/data \ --restart always \ whyour/qinglong:latest启动后浏览器访问http://服务器IP:5700首次打开会让你设置初始化密码按照页面提示操作即可。9.2 依赖管理为什么脚本总是缺模块青龙头疼的问题之一就是依赖管理。不同脚本要的包不一样有的要 Python 的requests有的要 Node 的axios有的要 Shell 环境。面板里虽然内置了依赖管理功能但还是经常有人踩“模块找不到”的坑。在青龙面板里进入“依赖管理” - “Node 依赖”或“Python 依赖”按脚本要求添加对应依赖。例如Node.js:axios,crypto-js,typescriptPython:requests,pycryptodome,beautifulsoup4安装后重启青龙容器docker restart qinglong这是我的经验青龙面板里执行脚本时环境变量和已安装的依赖需要在一个“干净的会话”里生效刚装完依赖不重启容易出现“明明装了却报 not found”。这不是面板缺陷而是运行时的缓存问题。9.3 环境变量的使用与安全青龙面板的“环境变量”功能很实用可以把账号密码、Token 这类敏感信息从脚本里剥离。脚本运行时通过环境变量读取配置不同环境切换也方便。但我必须提醒一点青龙管理面板不要直接暴露到公网否则配置、日志和数据都有被读取的风险。建议至少做一层 IP 白名单或者使用带认证的反代层。不要用默认端口裸奔。10. 常用命令速查与高频问题排查10.1 Docker 命令速查表场景命令拉镜像docker pull nginx启动容器docker run -d --name web -p 8080:80 nginx查看容器docker ps -a查看日志docker logs -f web进入容器docker exec -it web bash停止/启动容器docker stop web/docker start web删除容器docker rm -f web删除镜像docker rmi nginx构建镜像docker build -t myapp:1.0 .查看网络docker network ls查看数据卷docker volume ls清理无用资源docker system prune -a查看资源占用docker statsdocker stats我在排查容器性能问题时经常用能看到每个容器的 CPU、内存、网络 IO。如果发现某个容器内存持续飙高先看它再决定是不是要加资源限制。10.2 高频问题排查实录问题一Docker Desktop 报虚拟化未开启表现启动 Docker Desktop 直接报virtualization support wasnt detected或者 WSL 启动失败。排查思路任务管理器 - 性能 - CPU看右下角“虚拟化”是否显示“已启用”。没启用就去 BIOS 开启 Intel VT-x 或 AMD-V。启用后执行wsl --update然后wsl --shutdown重启 WSL。确认“虚拟机平台”和“Windows 虚拟机监控程序平台”这两个 Windows 功能已开启。这几个步骤按顺序走完绝大多数情况都能解决。问题二端口被占用表现docker run时提示Bind for 0.0.0.0:8080 failed: port is already allocated。解决换一个宿主机端口比如-p 8081:80或者先查找占用程序netstat -ano | findstr 8080 taskkill /PID 进程号 /F容器里的端口映射只跟宿主机端口冲突有关容器内部 80 端口不变所以外面用 8081 访问完全没问题。问题三容器内时区不对表现日志时间比本机差 8 小时。解决启动时加-e TZAsia/Shanghai。如果容器已经跑了可以在配置文件里加TZAsia/Shanghai后重建容器。容器重建是常态数据放在卷里就不会丢。问题四镜像拉取一直超时表现docker pull卡住或者报timeout。解决配置镜像加速器。Docker Desktop 和 Docker Daemon 都支持 registry-mirrors 配置。使用国内可用的公共加速地址但在生产环境建议自建仓库避免依赖第三方服务。问题五容器一直重启表现docker ps看到 STATUS 是Restarting。解决先看日志docker logs --tail 100 container大部分情况是应用启动时报错比如数据库连不上、配置文件解析失败。还有一种情况是启动后立刻退出的守护进程类服务日志里会显示 daemon exited。把日志贴到搜索引擎基本能找到原因。问题六磁盘空间被 Docker 占满表现服务器报磁盘满/var/lib/docker目录疯狂增长。解决先清理无用镜像和构建缓存docker system df docker system prune -aprune -a会删除所有未被容器使用的镜像小心使用。构建缓存很大定期清理有奇效。日志文件也要注意容器日志默认无限增长我一般会给容器加上--log-opt max-size50m --log-opt max-file3单容器日志最大也就 150MB不会把磁盘打爆。10.3 还有一些话想留下来Docker 用久了你会发现大部分“坑”其实不是 Docker 本身而是对状态管理、网络模型和数据持久化的理解不到位。容器是露天的配置、数据、日志必须主动挂载出来容器是临时的删了重建是常态所以任何要保留的东西都不能只放在容器里。想通这两点Docker 的很多问题都能自己解了。我在实际使用中还有一个习惯每个服务都尽量留一份docker-compose.yml在项目目录里哪怕只是一个单容器服务。这样以后不管换新机器还是同事要复现环境一行命令就能搞定比翻历史命令快得多。上生产环境前再检查一遍数据卷是否挂载、资源限制是否设置、启动策略是否合理这几个检查点做完一般不会出事。
返回列表