新闻详情

新闻详情

首页 / 资讯中心 / 详情

Docker实战:从镜像容器到Docker Compose编排与排障

发布时间:2026/9/29 15:14:22来源:尧图网络
Docker实战:从镜像容器到Docker Compose编排与排障
1. 写在前面为什么我建议你认真学一下Docker如果你最近两年一直在折腾服务器、部署应用、搭环境那你大概率已经无数次撞见“Docker”这个关键字了。不管你是想在自己的Windows电脑上跑一个Redis主从还是想把团队微服务项目一键拉起来又或者是刚接触青龙面板、GitLab私有仓库甚至光猫网关MediaMTX这类偏门服务Docker几乎成了绕不开的底层基建。我第一次用Docker的时候其实是带着情绪的好好的MySQL装在服务器上不就行了吗为什么要多套一层容器直到我连续三次因为“在服务器上装了新东西把老环境搞挂”而通宵排查后才算真正理解容器的价值——它是环境层面的“快照箱”你装坏了大不了扔了重建完全不碰宿主机。后来我买的服务器越来越多从便宜的VPS到家里的NASDocker成了我部署任何项目的首选方案。这篇内容会把我从入门到实战这几年踩过的坑整体梳理一遍包括安装配置、基础命令、写Dockerfile打包自己的应用以及网络、存储、日志这些日常最容易出问题的环节。我不会给你画一张庞大的概念地图那只会让你更快放弃。我按“第一天用起来”的顺序来写目标是你照着做到最后能把自己写的小项目打包成镜像扔到一台干净的服务器上直接跑起来。不管你是Windows用户还是纯Linux用户这篇都照顾到了。Windows那边会重点说说Docker Desktop在Hyper-V、WSL2之间折腾的那些事Linux这边说清楚命令行一把梭怎么最稳。好我们直接开始。2. 安装别小看第一步环境不对后面全是坑2.1 WindowsDocker Desktop 的两种底子Windows下目前没有选择余地官方推荐的方案就是Docker Desktop它底层支持两种模式基于Hyper-V的虚拟机和基于WSL2的后端。早年间只有Hyper-V一条路现在微软把WSL2做得越来越顺手导致很多Windows 10/11用户默认就走WSL2路线。我个人的建议是除非你在公司电脑上无法开启虚拟机平台否则优先用WSL2模式。原因是WSL2的文件读写性能、启动速度、资源占用都明显优于Hyper-V方案而且很多Linux下的Docker操作可以直接在WSL发行版里执行调试起来更顺手。但WSL2也有它的老毛病第一docker desktop 启动时如果报“Virtualization support not detected”“Docker Desktop failed to start because virtualization is disabled”这类错误多半是BIOS里虚拟化开关没开或者Windows的“虚拟机平台”功能没启用第二Windows防火墙有时会拦截WSL与宿主机的通信导致宿主机浏览器访问容器端口失败。我给你的保险操作流程是先打开“控制面板 - 程序 - 启用或关闭Windows功能”把“适用于Linux的Windows子系统”和“虚拟机平台”两项勾上重启电脑再进入BIOS确认Intel VT-x或AMD-V处于开启状态然后安装WSL2内核更新包最后再装Docker Desktop。任何一步漏了后面都是连环报错。安装完成后Docker Desktop默认使用的WSL发行版如果没改过一般是docker-desktop专用发行版。你别觉得这个概念复杂可以这么理解Docker引擎跑在Linux内核上Windows通过WSL2分发内核来承载它你所有命令其实是发送给这个“隐性Linux系统”的。2.2 LinuxUbuntu和CentOS的安装细节如果是纯Linux服务器命令行安装最省心。Ubuntu系列我建议直接走官方apt仓库sudo apt-get update sudo apt-get install ca-certificates curl gnupg lsb-release sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg sudo chmod ar /etc/apt/keyrings/docker.gpg然后写入源信息这里注意系统版本代号要和lsb_release -cs保持一致echo \ deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable | sudo tee /etc/apt/sources.list.d/docker.list /dev/null sudo apt-get update sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-pluginCentOS系则是sudo yum install -y yum-utils sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo yum install -y docker-ce docker-ce-cli containerd.io sudo systemctl start docker sudo systemctl enable docker如果你用的CentOS是7且系统内核比较老很可能会遇到docker服务启动失败的情况报错信息五花八门常见的是iptables相关或overlayfs相关。我遇到过CentOS7内核版本3.10下老版本Docker直接起不来升级内核后问题才消失。现在很多云服务器CentOS7默认跑的是3.10内核这确实是痛点建议要么换Ubuntu要么升级内核。Linux安装后还有一个高频问题权限。每次执行docker命令都要sudo很烦吧把当前用户加入docker组重新登录一下终端就好sudo usermod -aG docker $USER但是——这里必须加个但是——这也意味着任何有docker组权限的用户都等同于root因为docker本身就有提权风险。个人服务器这么干没问题生产环境要有安全意识别随意给用户加docker组。2.3 权限和启动失败的通用排查我自己生产环境踩过最典型的坑docker服务启动失败systemctl status docker看不到明确原因翻日志才发现是磁盘满了。容器日志默认存放在/var/lib/docker/containers目录下长时间不清理镜像和日志能把磁盘撑爆。后面专门写日志和清理策略。另一个常见启动错误是Ubuntu上apparmor与docker冲突或SELinux状态不对。CentOS上如果SELinux处于enforcing模式docker容器挂载目录时经常会权限异常临时测试可以用setenforce 0生产环境建议写好SELinux策略或改用Ubuntu。3. 镜像、容器、仓库把这三个概念焊死在脑子里3.1 一张图理解它们的关系很多人看教程一上来就敲docker run敲是敲会了遇到需要自定义镜像时彻底懵圈。本质上你得先把三个概念的内外关系理清镜像Image一个可执行的只读模板类似虚拟机的“快照”或装系统的“ISO”。它包含操作系统基础层、运行环境、依赖库、应用代码和启动命令。容器Container镜像是模板容器是模板的运行实例。就像类和对象的关系。同一个镜像可以同时跑多个容器互不干扰。仓库Registry存放镜像的地方。Docker Hub是最大的官方仓库也可以搭私有仓库比如Harbor、或者简单用registry镜像。可以这么记你拿一个ISO装出两台互不影响的虚拟机ISO就是镜像两台虚拟机就是容器。而“仓库”就是一堆ISO的光盘柜子。3.2 常用命令够用派别背几十条我见过很多人在入门时拿命令表背我明确告诉你没必要。日常操作高频命令我帮你筛选好了# 拉镜像 docker pull nginx:latest # 跑容器前台/后台 docker run -d --name web -p 8080:80 nginx docker run -it --rm ubuntu:22.04 bash # 查看容器和镜像 docker ps -a docker images # 进入运行中的容器 docker exec -it web bash # 日志 docker logs -f web # 删除 docker rm -f web docker rmi nginx:latest # 构建镜像 docker build -t my-app:v1 . # 组合管理 docker-compose up -d不要被-d、-it、--rm这些参数吓到用多了自然形成肌肉记忆。先掌握这一套再需要高级参数时现查即可。3.3 拉镜像慢、拉不动、超时怎么破只要是国内服务器第一天拉镜像大概率遇到“pull access denied”“timeout”或者慢到怀疑人生。这不是你操作问题是网络原因。解决方案很简单配置镜像加速器。这是很多教程不写透的地方。以docker desktop为例你在Settings的Docker Engine里找到JSON配置加一段{ registry-mirrors: [ https://docker.m.daocloud.io, https://dockerproxy.com ] }Linux上直接编辑/etc/docker/daemon.json改完重启dockersudo systemctl daemon-reload sudo systemctl restart docker需要注意镜像加速器只能加速拉取不能解决所有仓库访问异常部分企业内部私有仓库需要额外配置insecure-registries加在daemon.json的同一个文件里{ insecure-registries: [192.168.1.100:5000] }4. 实战案例一用Docker安装Redis主从4.1 为什么拿Redis主从练手Redis主从应该是刚入门时性价比最高的练习项目。它既有配置文件、端口映射、数据持久化又涉及多容器之间的网络通信但整体又足够简单不太会出现定位不了的玄学错误。我在热搜词里看到很多人搜“docker安装redis主从”说明大家在实际工作里确实需要这一套。我们这里用最标准的两个节点方案一个主节点master一个从节点slave。4.2 完整操作步骤首先建一个工作目录把配置和持久化数据放外面方便修改与备份mkdir -p ~/redis-cluster/data cd ~/redis-cluster创建主节点redis.confport 6379 appendonly yes appendfilename appendonly.aof requirepass yourpassword然后运行主容器docker run -d \ --name redis-master \ -p 6379:6379 \ -v ~/redis-cluster/data:/data \ -v ~/redis-cluster/redis-master.conf:/etc/redis/redis.conf \ redis:7.2 redis-server /etc/redis/redis.conf从节点的配置关键在replicaof这一行port 6379 replicaof 172.17.0.2 6379 masterauth yourpassword appendonly yes这里要注意replicaof后面的IP不能写127.0.0.1因为容器之间通信走的是Docker内部网络。你先不要急着自己猜IP跑一下命令看主容器的IPdocker inspect redis-master | grep IPAddress把输出的IP填进从节点配置再跑从容器docker run -d \ --name redis-slave \ -p 6380:6379 \ -v ~/redis-cluster/slave-data:/data \ -v ~/redis-cluster/redis-slave.conf:/etc/redis/redis.conf \ redis:7.2 redis-server /etc/redis/redis.conf进入主节点写数据再到从节点查数据能同步就说明这套链路通了docker exec -it redis-master redis-cli -a yourpassword set name docker-redis docker exec -it redis-slave redis-cli -a yourpassword get name4.3 我踩过的坑和关键心得第一容器重启后IP会变化。上面直接写死IP的做法只适合实验环境。生产环境应该用Docker网络的自定义网桥或者用docker-compose让服务名互相解析。后面docker-compose章节我再展开。第二从节点默认是只读的这个不是配置错了是设计如此。第三很多人挂了配置文件却启动失败多半是容器里的redis用户没权限读取挂载文件或者是文件权限不对。最常见错误是Windows下编辑的配置文件带有CRLF换行符Linux容器加载时报错。解决方法很简单用dos2unix转换一下或者直接用VS Code设置换行符为LF再保存。第四如果你想在Windows的Docker Desktop里跑这套注意把-p 6380:6379改成-p 63790:6379这种高位端口避免Windows本机端口冲突。5. 实战案例二MySQL 8.0部署和常见失败排查5.1 一条命令跑起来但要考虑好数据目录MySQL比起Redis要“重”不少光环境变量和初始化就要小心。最简启动docker run -d \ --name mysql8 \ -e MYSQL_ROOT_PASSWORDroot123 \ -e MYSQL_DATABASEtestdb \ -p 3306:3306 \ -v ~/mysql-data:/var/lib/mysql \ mysql:8.0这里关键在于-v ~/mysql-data:/var/lib/mysqlMySQL数据文件直接写到宿主机目录容器删了数据还在否则容器一删数据全没。但是很多人在这一步就踩坑了。如果你把-v挂载到一个空目录MySQL初始化时会检查权限容器里mysql用户UID是999宿主机目录如果是root用户创建权限不对会导致无法写入报错一般是“chown: changing ownership of /var/lib/mysql/: Permission denied”或“mysqld: Cant change ownership of database directory”。解决办法先给目录授权再启动sudo chown -R 999:999 ~/mysql-data或者更简单直接用命名的volume让docker自己管理权限docker volume create mysql-data docker run -d --name mysql8 -e MYSQL_ROOT_PASSWORDroot123 -v mysql-data:/var/lib/mysql -p 3306:3306 mysql:8.05.2 宿主连接、字符集和双重端口问题MySQL8默认鉴权插件是caching_sha2_password如果你用老版本navicat或PHP5连接极容易报“Authentication plugin caching_sha2_password cannot be loaded”。这种情况我建议在启动命令里加参数--default-authentication-pluginmysql_native_password或者进入容器后改用户ALTER USER root% IDENTIFIED WITH mysql_native_password BY root123; FLUSH PRIVILEGES;还有字符集问题。许多人跑起来后数据写入正常但中文变问号大概率是容器默认字符集不是utf8mb4。启动参数补上--character-set-serverutf8mb4 --collation-serverutf8mb4_unicode_ci另外一个容易忽略的点如果本机3306端口已经被原来的MySQL占用docker run会失败日志显示“port is already allocated”。很多人第一时间怀疑镜像错了其实查一下端口占用就明白。5.3 容器重启后数据还在不在这个问题问的人很多我讲清楚如果你的MySQL容器删除后重新run并且用的是同一个数据卷数据都还在。但如果你用docker logs看到的是全新初始化的日志说明你没挂载对。测试方法在容器里建一张表插数据然后docker rm -f mysql8再重新docker run一遍挂同一个卷查表数据应该还在。这一步建议所有人亲手试一次建立起“数据放卷里容器随便删”的直觉。6. Docker网络不通排查思路和解决路径6.1 容器通信常见的三大类原因既然走到部署微服务或多容器的阶段网络几乎必然出问题。“docker网络不通”是热搜词我见过的问题集中在三类第一类是容器与宿主机端口映射不通。宿主机浏览器访问http://localhost:8080打不开要依次排查容器是否真的在监听8080、docker ps是否正确显示端口映射0.0.0.0:8080-80/tcp、防火墙是否放行。第二类是容器与容器之间不通。比如Redis主从、微服务调用数据库都是这一种。常见原因是两个容器在没有自定义网络时各自使用默认bridge互相用IP访问时会因为IP变化或网络隔离而失效。解法是创建自定义网络docker network create app-net docker run -d --name mysql8 --network app-net ... docker run -d --name backend --network app-net ...处于同一自定义网络的容器可以用容器名互相访问。backend容器里连MySQL直接写mysql8:3306即可不用记IP。第三类是容器访问外网不通。容器里curl百度超时、apt update失败。大概率是宿主机的DNS配置在容器里继承出了问题。解决方案运行容器时增加dns参数docker run -d --dns 223.5.5.5 ...或在daemon.json里配置全局DNS。6.2 一个真实排障案例有一次我的Nginx容器反代后端服务访问时总是502 bad gateway日志又显示连接被拒绝。我把后端容器的端口映射关了因为不想暴露外部只用自定义网络通信结果忘记把Nginx的配置从localhost:8080改成后端服务名:8080。折腾了半小时才发现。教训很直接默认bridge网络下容器之间只能用IP访问自定义网络下才可以用容器名。你如果看到502/Connection refused先看配置里“地址”部分别急着怀疑容器挂了。6.3 端口映射的特殊情况kali搭建DVWA靶场、青龙面板、kodbox这类需要Web访问的场景端口映射看起来不难但有个细节如果你用docker run -p 80:80做映射实际是监听所有网卡。如果只想本机访问更安全的写法是localhost:80:80或127.0.0.1:80:80。还有一类坑是IPv6网络环境。如果你在云主机上配置了IPv6容器默认可能只监听IPv4导致IPv6请求无法访问。这时候建议在启动参数里追加-p [::]:80:80/tcp映射或者直接关闭IPv6。7. Dockerfile把应用打包成标准交付件7.1 为什么必须会写Dockerfile很多教程教完run就会让人下载现成镜像跑起来但真实项目中你迟早要面临一个问题我写的PHP项目、Java SpringBoot服务、Python爬虫怎么变成别人一条命令就能跑起来的镜像这正是Dockerfile的价值把环境配置、依赖安装、代码拷贝、启动命令全部写进一个文本文件任何机器上构建出的镜像行为一致。这也是“Docker部署微服务项目”的基础。7.2 一个最小可用的Node.js示例假设你有一个简单的Node应用项目目录里包含app.js、package.json。多阶段构建是最好的实践# 第一阶段构建 FROM node:18-alpine AS build WORKDIR /app COPY package*.json ./ RUN npm install COPY . . # 第二阶段运行 FROM node:18-alpine WORKDIR /app COPY --frombuild /app ./ EXPOSE 3000 CMD [node, app.js]很多人新手会疑惑为什么需要两个FROM因为最终镜像不应该包含源码编译时需要的多余文件、缓存、工具包多阶段构建能极大减小镜像体积。这个习惯越早培养越好。7.3 Java和PHP打包的其他形式Java生态最常见的打包方式是先用Maven或Gradle在宿主机打出jar包再写Dockerfile拷贝jar。如果你的Maven环境没配置好也可以用maven镜像先完成打包再拷贝省得在宿主机装JDK和MavenFROM maven:3.8-openjdk-11 AS build WORKDIR /app COPY pom.xml . RUN mvn dependency:go-offline COPY src ./src RUN mvn clean package -DskipTests FROM openjdk:11-jre-slim WORKDIR /app COPY --frombuild /app/target/*.jar app.jar EXPOSE 8080 ENTRYPOINT [java, -jar, app.jar]PHP项目则要看是传统Apache/Nginx还是PHP-FPM架构。简单场景直接FROM php:8.2-apache把代码拷贝进/var/www/html即可复杂一点要装扩展就得写RUN docker-php-ext-install pdo_mysql之类这也是PHP里专门用docker部署时最容易卡住的地方因为PHP官方镜像把编译扩展的命令封装成了docker-php-ext-install新手不知道。7.4 .dockerignore和构建缓存我见过很多人在打完包后镜像体积巨大或意外包含敏感文件都是因为没写.dockerignore。它的作用类似.gitignore避免把node_modules、target、.git、.env等文件拷进构建上下文node_modules target .git .env *.log还有一个关键机制是构建缓存。Dockerfile中每条指令如果没变化会复用之前的缓存层。这就是为什么我习惯先COPY package*.json再RUN npm install再COPY其他文件。只要依赖文件没变即使业务代码改了几次构建时npm install仍然走缓存节省大量时间。7.5 ENTRYPOINT和CMD的区别热搜词里有“docker中的enterpoint命令和run命令”我想这个指的是ENTRYPOINT和CMD。区别很简单CMD容器启动默认执行的命令但docker run后面跟参数时可以覆盖它。ENTRYPOINT容器的固定入口不容易被docker run的参数覆盖适合固定不可变的启动命令。最佳实践是组合使用ENTRYPOINT指定主程序CMD提供默认参数。效果上类似ENTRYPOINT [nginx] CMD [-g, daemon off;]这样运行时你还能追加参数docker run ... -g daemon off;但不会替换掉nginx本身。8. Docker Compose多容器编排的救命稻草8.1 为什么有了docker run还要Compose单个容器用docker run完全OK但一旦涉及微服务项目前端、后端、数据库、缓存、消息队列你要写好几条docker run命令还要保证启动顺序、网络连通、数据卷一致。人会疯的。docker-compose.yml把服务、网络、卷、环境变量声明式地写在同一个文件里一条docker compose up -d全部启动。对我这种习惯把整个项目配置托管到Git仓库的人来说这才是真正可复现的部署单元。8.2 一个标准的Compose文件长什么样以最常见的应用MySQL为例services: app: build: . container_name: myapp ports: - 8080:8080 environment: SPRING_DATASOURCE_URL: jdbc:mysql://db:3306/testdb?useSSLfalse SPRING_DATASOURCE_USERNAME: root SPRING_DATASOURCE_PASSWORD: root123 depends_on: - db restart: unless-stopped db: image: mysql:8.0 container_name: mysqldb environment: MYSQL_ROOT_PASSWORD: root123 MYSQL_DATABASE: testdb volumes: - db_data:/var/lib/mysql ports: - 3306:3306 restart: unless-stopped volumes: db_data:注意两个细节一是app连接数据库的地址写的是db而不是localhost因为在同一个compose网络里服务名就是主机名二是depends_on能保证db先启动但它只保证“容器起来了”不代表MySQL初始化完成。如果要更严谨需要健康检查healthcheck配置。8.3 青龙面板这类多组件项目如何套Compose现在很流行的青龙面板在Docker中部署实际是把几个服务组合在一起面板本身、依赖的数据库、消息推送、运行环境。我看热搜里有“docker青龙依赖管理”很多人手工部署时控制依赖很痛苦但用compose就能统一环境变量。其实不只是青龙任何你看到“docker run一长串参数”的镜像都可以改写为compose配置然后项目交接的时候把那份yaml发给别人他直接复现同样的环境。这是为什么Compose值得专门学习。8.4 Compose项目升级和迁移当你的项目要挪到新服务器时别傻到手动重新创建容器。正确做法把docker-compose.yml、环境变量文件、数据卷备份拷到新机器执行docker compose up -d几乎零迁移成本。这里有个惨痛教训如果你做数据卷的时候用的是bind mount比如/home/user/data迁移时必须同步拷贝那个目录如果你用的命名卷需要docker run --volumes-from或使用专用迁移工具否则数据全丢。9. 青龙面板部署与依赖管理延展案例9.1 青龙面板是什么为什么火青龙面板是一个定时任务管理平台常被用来跑各类定时脚本、签到脚本等支持Python、JavaScript、Shell多种脚本语言。因为功能清爽、可视化好很多开发者把它部署在服务器或软路由上用来管理定时任务。注意我在这里不展开具体脚本内容只讲Docker部署本身。官方最简部署方式docker run -d \ --name qinglong \ -p 5700:5700 \ -v ~/qinglong/data:/ql/data \ --restart unless-stopped \ whyour/qinglong:latest访问http://宿主机IP:5700即可通过Web界面配置任务。9.2 依赖管理我看到的“依赖”痛点依赖管理是青龙面板部署里的麻烦点。面板本身提供一个“依赖管理”功能可安装Python、Node、Linux相关的依赖包但新手经常遇到“依赖安装失败”或“脚本运行提示找不到模块”。这里要明白一个概念运行脚本的Python或Node环境在容器内部。你在宿主机pip install的包对容器内脚本毫无用处。必须在面板的依赖管理里安装或进入容器手动装docker exec -it qinglong bash pip3 install requests但更稳的做法是把依赖声明写进compose或Dockerfile的构建过程避免每次容器重建后都要重复安装。9.3 青龙升级注意升级青龙如果要保留数据务必提前备份/ql/data目录。有些版本跨版本升级后数据库格式变化直接大版本跳跃可能出问题。我的习惯是升级前先打一个数据卷快照或直接把整个data目录压缩存一份多花两分钟出事后能救命。10. 仓库管理从Docker Hub到私有仓库10.1 Docker Hub真的够用吗Docker Hub是公共镜像仓库但有两个问题一是网络问题明显二是企业内或私有代码库不能直接推上去。所以了解私有仓库配置很有必要。最轻量级的私有仓库就是用registry镜像docker run -d \ --name registry \ -p 5000:5000 \ -v ~/registry-data:/var/lib/registry \ registry:2推镜像前需要给镜像打上私有仓库地址标签docker tag my-app:v1 localhost:5000/my-app:v1 docker push localhost:5000/my-app:v1其他服务器拉取时需要在该服务器的daemon.json中配置insecure-registries要不然HTTPS证书校验会一直报错。10.2 镜像命名和Tag管理技巧很多团队镜像管理混乱因为没有约定Tag规范。我的建议是至少包含版本号和构建时间或Git提交号比如my-app:20250215-abc1234。不要只用latest生产环境用latest是灾难因为你不知道拉下来的是哪天的版本。10.3 从GitLab CI到Docker仓库的自动化如果你已经在用GitLab社区版也可以启用GitLab Runner结合gitlab-ci.yml实现代码提交后自动构建镜像并推送到私有仓库。这一套组合还是目前中小团队最务实的落地路径。GitLab社区版的Docker部署本身就依赖容器部署和升级路径都比较成熟。部署时注意内存要充足至少给4G否则GitLab经常被OOM干掉这应该是全员共识了。11. 常见问题与报错速查表11.1 启动类报错我在热搜词里看到好几个具体报错这里一个个说清楚Docker Desktop failed to start because virtualization is disabled这是Windows下最典型的提示。核心意思是虚拟化没开或Windows功能没启用。按我前面2.1节说的三步走90%能解决。failed to connect to the docker api at npipe:////./pipe/dockerdesktoplinuxengineWindows下常见的“连不上Docker引擎”错误。一般是Docker Desktop没有真正启动成功或WSL发行版没起来。解决办法是重启Docker Desktop或在PowerShell里执行wsl --shutdown后重新start。Cannot connect to the Docker daemon at unix:///var/run/docker.sockLinux下cmd执行时最常见的报错。原因是docker服务没启动或者当前用户无权限访问socket。先systemctl start docker再确认是否在docker组。11.2 拉取与构建类报错manifest unknown拉取镜像时tag名写错或私有仓库里不存在该tag。denied: requested access to the resource is denied可能是镜像不存在也可能是Docker Hub上权限不足检查登录状态docker login。no space left on device磁盘满了用docker system prune清理但注意这个命令会删除所有未被容器使用的镜像、网络和构建缓存请谨慎。如果只想清理日志和已停止容器用docker container prune更安全。11.3 运行类报错port is already allocated端口占用netstat -tulnp检查。standard_init_linux.go: exec user process caused exec format error通常是架构不对。你在x86服务器上构建的镜像推到ARM设备比如树莓派、部分NAS会报这个错误。用docker buildx构建多架构镜像解决。permission denied while trying to connect to the Docker daemon socketLinux权限问题参照2.2节加入docker组。OCI runtime exec failed执行docker exec时容器内没有bash改用sh或者容器本身已挂掉。11.4 自检清单与调试习惯排查问题一定按顺序来先docker ps确认容器状态再看docker logs最后网络测试。不要上来就猜配置。很多看起来玄学的问题docker logs都会给出真正的线索。有一个小习惯我很推荐加个-p参数不一定有用但在容器里执行命令时总能看到更多细节。比如容器内部访问网络可以用docker exec -it 容器名 curl 目标地址立刻区分是容器内问题还是映射问题。12. 资源限制与优雅启停生产环境必备素养12.1 内存和CPU限制Docker容器不加限制时能用完宿主机所有资源。多个容器互相争抢导致宿主机崩溃的案例并不少。我建议所有生产容器都加限制至少内存限制docker run -d --memory512m --cpus1.5 ...Compose里同样配置services: app: deploy: resources: limits: cpus: 1.5 memory: 512M限制并不难理解它的意义在于防止一个容器拖垮整台服务器。12.2 优雅停止和重启策略docker stop默认等待10秒后kill如果应用需要完成事务设置更长的停止超时docker stop -t 30 container_name容器在接收SIGTERM后应该自行处理收尾这对Java应用尤其重要因为Spring Boot等框架需要时间优雅关闭。重启策略有四种级别我推荐多数服务用unless-stopped这样即使服务器重启后docker自动拉起容器但你手动停掉容器后它不会自动再启动。生产环境请设置日志轮转否则日志文件无限增长。方法是在daemon.json里加{ log-driver: json-file, log-opts: { max-size: 10m, max-file: 3 } }13. 结尾最后说点实在话学了这么多最后聊一聊我的个人体会。Docker真正改变的不是技术栈本身而是部署心态。以前我改个配置要在服务器上小心翼翼生怕搞崩环境现在我改坏了大不了docker rm -f再重新run镜像变了就重新build。这种“环境可以随便扔”的底气只有真正把镜像、卷、容器这三层关系用顺了之后才能体会到。如果你接下来准备自己动手练我建议一条最直接的学习路径先把官方Docker Hub里的Nginx镜像跑起来改默认页面看看宿主机浏览器能不能访问然后写一个最简单的Node或Python应用打包成镜像放到另一台干净服务器上运行最后把两个服务用docker-compose编排起来连上数据库模拟一次微服务调用。走完这三步日常工作中90%的Docker场景你就能应付了。我现在自己上手的习惯是任何部署项目先写compose文件和.env配置把密码、端口、数据卷都固定好再一键拉起。这套方式花的时间可能比手动run多条命令多一点但维护收益是几何级数增长的。希望这篇能把Docker这个工具讲得“能落地”而不是“概念好看”。有任何问题欢迎在评论区带着你的报错信息来找我我大概率也踩过同一个坑。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

UE5 C++开发环境配置:Visual Studio 2022安装与调试指南 2026/9/29 19:17:44

UE5 C++开发环境配置:Visual Studio 2022安装与调试指南

1. 为什么UE5 C开发绕不开Visual Studio 2022 很多人第一次打开UE5编辑器,用蓝图连了几个节点,觉得“这不挺好吗,要C干嘛”。等到项目稍微大一点,蓝图资产上千个,编译一次要等十几分钟,或者需要接入第三方S…

阅读更多 →
AI绘画工具与提示词实战:本地部署、参数调优与高效出图指南 2026/9/29 19:17:44

AI绘画工具与提示词实战:本地部署、参数调优与高效出图指南

1. 先搞清楚“全网最强”到底强在哪1.1 为什么我不推荐一上来就装一堆软件刚接触AI绘画那会儿,我跟很多人一样,看到“全网最强”“一键出图”“无禁词免费”这类字眼就忍不住点进去,结果电脑里装了七八个工具,每个都只打开过一两次…

阅读更多 →
CLI-Anything:用管道抽象和插件机制统一命令行数据处理 2026/9/29 19:17:44

CLI-Anything:用管道抽象和插件机制统一命令行数据处理

我最早想做这个工具,是被一条命令逼急的:需要把一批 Markdown 文件统一转换成正文字符数统计表,又要按目录归类,又要输出成 CSV,还要顺带把里面的外链全部拉出来验证一遍可访问性。手写 Python 脚本到一半就放弃了&…

阅读更多 →
RIDER Breast MRI预处理实战:梯度下降配准与朴素贝叶斯增强 2026/9/29 19:17:44

RIDER Breast MRI预处理实战:梯度下降配准与朴素贝叶斯增强

简介:这份PDF文献面向医学影像处理、深度学习方向的研究生与算法工程师,聚焦乳腺癌MRI影像的预处理环节,帮助读者解决原始影像存在形变与噪声、难以直接用于特征计算与建模的问题。资源为单篇学术论文,共1个PDF文件,压…

阅读更多 →
OSGB模型导入3dsMax全攻略:插件选择与关键步骤解析 2026/9/29 19:17:44

OSGB模型导入3dsMax全攻略:插件选择与关键步骤解析

先声明一下,这篇不是写给纯看热闹的人看的。做三维GIS、智慧城市、CIM平台或者倾斜摄影后期处理的朋友,应该都遇到过同一个墙:倾斜摄影出来的OSGB模型质量确实好,真实感强,但到了3dsMax里就变成了一堆不听话的数据。想…

阅读更多 →
QT HTTP文件下载实战:断点续传、并发控制与跨平台稳定方案 2026/9/29 19:17:05

QT HTTP文件下载实战:断点续传、并发控制与跨平台稳定方案

1. 项目概述:为什么QT里做HTTP文件下载不是“调个QNetworkAccessManager就完事”?在QT开发中,遇到“需要从服务器拉一个配置文件”“用户点击按钮下载日志包”“自动更新本地资源目录”这类需求时,很多人第一反应是翻文档找QNetwo…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉