
把“Docker基础、安装、核心命令及网安应用”这串词拆开看前三个是开发和运维的基本功最后一个是安全从业者的工具箱。成天听人说“容器化部署”可真到了自己动手镜像拉不下来、权限报错、端口不通、启动失败任何一个问题都能卡一下午。这篇文章我按自己踩过的坑来写先带你把Docker的底子补上再讲怎么把它装好、常用命令怎么用最后用几个真实场景串起网络安全方向的应用。适合刚接触Docker的开发者、要维护环境的运维以及想在授权测试里快速搭靶场的安全人员。1. 先搞清楚Docker是干什么的很多人一上来就去敲命令结果敲完发现自己连“镜像”和“容器”的关系都说不清。基础不牢后面所有安装和排错都会变成玄学。所以我建议先花十分钟把Docker的几个核心概念理顺这个时间花得值。1.1 镜像、容器、仓库三角关系一次说清Docker世界里反复出现三个词镜像、容器、仓库。我用一个生活化的例子解释。镜像可以理解成一张“光盘”里面刻好了操作系统、应用程序、依赖库和最基础的配置它本身是只读的不会因为你运行过一次就改变。容器就是拿这张光盘“启动”出来的一个运行实例相当于你把自己的电脑启动成光盘里的系统你在里面改文件、跑程序都是在这个实例里发生的。仓库则是存放镜像的地方默认的公共仓库叫Docker Hub国内也有一堆镜像站可以拉取。我见过很多新人混淆的一点是docker pull是从仓库把镜像拉到本地docker run才是用镜像创建容器docker build是把Dockerfile构建成一个镜像docker push是把自己的镜像传到仓库。这四条命令构成了Docker最基本的工作流。你本地可以没有仓库也可以没有镜像但只要有镜像就能跑容器这是后续所有操作的前提。镜像本身还有一个很关键的特性分层存储。每个镜像由多层只读文件系统叠加而成拉镜像的时候如果某些层你已经有了就不会重复下载。多个容器共享同一个底层镜像时底层只有一份拷贝这也正是Docker能在小主机上同时跑几十个容器的根本原因。1.2 容器为什么比虚拟机轻以前大家装个MySQL、Redis最稳的办法是开一台虚拟机一个VM动辄几个GB的磁盘占用启动时间以分钟计。容器完全走另一条路它不虚拟一套完整操作系统而是直接复用宿主机内核通过namespace做隔离、通过cgroup做资源限制。你可以把容器理解成一群“合租室友”共享同一个厨房和厕所宿主机内核但每个人有自己的房间文件系统、进程、网络空间互相隔离。这个差异带来的体感是虚拟机是“冷启动”容器是“秒启动”虚拟机光系统占用就吃几个GB内存容器本身占的内存非常小跑十几个Nginx容器可能才几百MB。这也是为什么像Intel N100这种低功耗小主机能一口气跑20个Docker容器还不怎么卡。不过轻量是有代价的。虚拟机隔离的是内核级别的系统安全边界更硬容器和宿主机共享内核一旦内核漏洞被利用隔离就形同虚设。这个特点到第5章聊安全应用时要重点记住尤其是做恶意样本分析不能想当然地把容器当成保险箱。1.3 Docker擅长和不擅长的事提前心里有数Docker最典型的应用场景包括开发环境统一、CI/CD流水线、微服务部署、中间件快速拉起、安全靶场搭建。MySQL、Redis、Nginx、GitLab、Kodbox、Hadoop这类有官方镜像或社区成熟镜像的软件都是标准的容器化受益者。你用docker run一条命令把环境跑起来再也不用先装依赖、改配置、处理系统差异。但也有不适合用Docker的场景。比如需要极度严格的隔离环境做恶意软件深度分析容器不如独立虚拟机可靠再比如数据库对磁盘IO和内核参数有强依赖生产环境追求极致性能时裸机部署通常仍优于容器。docker pull时报错、docker run起不来很多时候不是你命令写错了而是这个软件根本不适合这种跑法。把这些问题想清楚接下来安装Docker时才不会迷迷糊糊。2. Docker安装Windows、Linux两条主流路线实测安装是劝退新手的第一道坎。Windows用户装Docker Desktop连报错都看不懂Linux用户装Docker Engine又会撞上各种历史遗留问题。这一章我把两条路的安装步骤和报错原因都摊开写你可以按自己的系统直接跳着看。2.1 Windows装Docker Desktop前先解决虚拟化Windows 10/11上装Docker Desktop最崩溃的报错长这样Docker Desktop failed to start because virtualisation support wasnt detected。这句话意思是Docker Detected不到虚拟化支持。Docker Desktop默认依赖WSL2或Hyper-V这两个组件都要求CPU开启硬件虚拟化。第一件事打开任务管理器切到“性能”标签页看CPU那一栏的“虚拟化”是否显示“已启用”。如果是“已禁用”需要重启进BIOS/UEFI把Intel VT-x或AMD SVM打开不同主板菜单名不一样搜“Virtualization Technology”或“SVM Mode”就行。这一步不做后面全白搭。确认虚拟化开启后以管理员身份打开PowerShell执行wsl --install wsl --update如果wsl --install提示不支持可以手动启用Windows功能Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux -All Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform -All执行完重启系统再安装Docker Desktop。装好后打开Settings确保“Use the WSL 2 based engine”是被勾选的。另外如果你之前装过VMware、VirtualBox这类第三方虚拟化软件它们会和Hyper-V抢虚拟化资源也会导致Docker Desktop起不来这时要么关掉第三方虚拟化软件要么彻底移除Hyper-V之后再试。2.2 Linux用命令行安装Docker EngineLinux下装的是Docker Engine没有图形界面全靠命令行操作。Ubuntu/Debian系最省事官方仓库一把梭sudo apt-get remove docker docker-engine docker.io containerd runc sudo apt-get update sudo apt-get install ca-certificates curl gnupg -y 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 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 -y sudo systemctl enable --now docker最后一条systemctl enable --now docker很多人会漏它的作用是让Docker开机自启并立即启动。装完验证一下docker version docker run hello-world如果docker run hello-world能打印出提示信息说明安装成功。老CentOS 7机器升级Docker会麻烦一些。CentOS 7默认内核是3.10新版Docker对内核特性有要求建议先升级到20.10.x这类兼容版本。安装路径是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-20.10.9 docker-ce-cli-20.10.9 containerd.io注意别直接写docker-ce不指定版本容易pull到和你内核不匹配的新版本装完启动就报错。2.3 装完后最常见的两个错误启动失败与权限拒绝Linux下启动Docker失败最常见的报错是Failed to start Docker Application Container Engine.。别急着重启先看日志journalctl -u docker --no-pager | tail -n 50根据我的经验八成是/etc/docker/daemon.json写坏了。比如JSON格式多了一个逗号或者配置了不存在的路径Docker daemon直接拒绝启动。还有一部分原因是SELinux如果日志里出现selinux关键字临时排查可以用sudo setenforce 0但长期方案是阅读Docker和SELinux的兼容文档而不是简单关掉。另一个高频报错是permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock这个错误本质是你当前用户没有访问Docker socket的权限。解决办法是把用户加进docker组sudo usermod -aG docker $USER newgrp docker加完组之后一定要重新登录或者重开终端否则权限不会生效。这个坑我在很多新手身上看到过命令执行完马上再敲docker ps还是报错于是就开始怀疑人生。2.4 镜像下载太慢配置一个能用的镜像源装好Docker之后第一个让人抓狂的问题是docker pull mysql:8.0结果卡在“Waiting”半天不动。国内直连Docker Hub的速度不稳定这是客观情况。不涉及任何乱七八糟的方案正规做法就是给Docker配一个可直连的镜像加速器。编辑/etc/docker/daemon.jsonWindows在Docker Desktop的Settings里配置Docker Engine JSON填入{ registry-mirrors: [ https://docker.m.daocloud.io, https://mirror.ccs.tencentyun.com ] }保存后重启Dockersudo systemctl daemon-reload sudo systemctl restart docker用docker info查看Registry Mirrors字段确认配置已经生效。之后拉镜像就有明显改善。注意镜像加速器只能加速公共镜像一些只发布在特定镜像仓库的企业镜像还是需要先docker login登录对应仓库或者用docker pull 仓库地址/镜像名:tag的完整形式拉取。3. 核心命令从拉取镜像到管理容器的完整链路命令是Docker的日常但日常用的命令其实不超过20条。这一章我不打算把docker --help抄一遍而是按一条完整的链路来讲找镜像、拉镜像、建容器、进容器、看日志、删容器。你把这个链路走通日常80%的操作就都会了。3.1 镜像管理search、pull、images、rmi找镜像用docker search比如docker search mysql它会返回一堆镜像列表。MySQL这样的热门软件有无数的第三方镜像我给你的建议是优先选官方镜像列表里带OFFICIAL标记的或者挑stars数高、更新时间近的。第三方镜像虽然可能带一些预设配置方便是方便但镜像供应链安全问题很多这个到第5章细说。拉镜像用docker pull强烈建议带版本标签docker pull mysql:8.0 docker pull redis:7.2 docker pull nginx:1.25-alpinedocker pull mysql不写标签默认拉latest。latest这个标签很具迷惑性它不一定是稳定版也有可能意味着你今天拉的和明天拉的不是同一个版本。生产环境里我见过太多因为latest版本漂移导致的诡异问题所以能指定tag就指定tag。看本地镜像用docker images它会列出仓库名、标签、镜像ID、创建时间和大小。删镜像用docker rmi 镜像ID或镜像名如果有容器正在使用这个镜像得先删容器再删镜像否则会报冲突错误。还有两条镜像命令很容易被忽略但很实用docker tag mysql:8.0 myregistry.example.com/prod/mysql:8.0 docker push myregistry.example.com/prod/mysql:8.0docker tag是给镜像打标签常用于准备推送私有仓库docker push是把镜像推送到仓库。自己维护私有镜像库的公司这两条是日常。3.2 容器生命周期run、ps、exec、logs、rm创建并启动容器是最高频操作先看标准模板docker run -d \ --name mysql8 \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORDYourStrongPass \ -v /data/mysql:/var/lib/mysql \ --restartalways \ mysql:8.0我来逐个解释参数-d表示后台运行--name给容器取名-p 3306:3306把宿主机3306端口映射到容器的3306端口这样外部可以通过宿主机IP访问容器里的MySQL-e传入环境变量MySQL镜像靠这个环境变量设置初始密码-v挂载数据卷把容器内/var/lib/mysql目录映射到宿主机/data/mysql防止容器删除后数据全丢--restartalways让Docker在容器异常退出时自动重启生产环境几乎必加。看容器列表用docker ps它只显示运行中的容器docker ps -a显示所有容器包括已退出的。看日志用docker logs -f 容器名-f表示持续跟踪输出排错时基本靠它。进入容器内部用docker exec -it mysql8 bash-it是-i和-t的组合保持标准输入打开并分配伪终端进去之后你就有个shell了。容器停止、启动、重启、删除docker stop mysql8 docker start mysql8 docker restart mysql8 docker rm -f mysql8rm -f是强制删除运行中的容器也会被直接删掉这个命令要小心删了就是删了。3.3 端口映射、数据卷和网络容器不是孤岛如果容器只是跑在宿主机内部别人访问不到那它就跟一个普通的轻量进程没区别。真正让容器有用的是三类“连接”网络、端口和数据。端口映射刚才讲过了-p 8000:80的意思是宿主机8000端口转发到容器80端口。这里有个容易踩的坑当你用docker ps看到0.0.0.0:3306-3306/tcp时说明端口已经暴露到宿主机所有网卡了如果你在云服务器上这么跑MySQL又没有安全组限制等于把数据库裸奔到公网。个人测试无所谓生产或测试环境一定要加防火墙规则或者指定-p 127.0.0.1:3306:3306只允许本机访问。数据卷解决的是“容器删了数据还在不在”的问题。容器本身是无状态的不挂载数据卷时里面的数据随着容器删除一起消失。挂载方式有两种docker run -v /data/mysql:/var/lib/mysql mysql:8.0 docker run -v myvolume:/var/lib/mysql mysql:8.0第一种是绑定挂载把宿主机绝对路径挂进容器第二种是命名卷由Docker管理存储位置。日常测试推荐绑定挂载因为你能直接去宿主机目录里看文件排查问题方便。网络方面Docker容器默认通过bridge网络互相通信。同一个bridge网络里的容器可以通过容器名互相访问外部访问才需要靠端口映射。告诉容器使用哪个网络用--network参数自定义网络先用docker network create mynet创建。不同宿主机上的容器互联是另一个话题一般靠overlay网络或直接把服务端口映射出来这里先不展开。3.4 Dockerfile和Compose把一条命令升级为一套方案docker run命令适合临时演示真要做项目和交付必须把部署逻辑写进Dockerfile和docker-compose.yml里。一个简单的PHP项目Dockerfile长这样FROM php:8.2-fpm-alpine WORKDIR /var/www/html COPY . . RUN docker-php-ext-install pdo_mysql EXPOSE 9000 CMD [php-fpm]构建镜像docker build -t my-php-app .镜像构建出来之后就可以用docker run或者写进compose跑。Dockerfile的威力在于“基础设施即代码”镜像的构建过程被完全记录团队其他人拿到仓库后执行一次构建出来的镜像和你的完全一致不会出现“在我机器上好好的”这种玄学。当服务数量增多一条docker run就管不过来了。比如微服务项目里常见的前端、后端、MySQL、Redis四件套我会写一个docker-compose.ymlversion: 3.8 services: web: build: . ports: - 8080:80 depends_on: - db db: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: YourStrongPass volumes: - dbdata:/var/lib/mysql volumes: dbdata:然后一条命令docker compose up -d所有服务按依赖顺序启动日志统一管理停止用docker compose down。Compose文件本身也可以提交到Git仓库环境一点点漂移都不会有。4. 实操现场MySQL 8.0与Redis主从的容器化落地前面讲了概念和命令这章直接上一个完整实操。我们把热搜词里出现最多的两个需求做掉一个是docker安装mysql8.0并使用一个是docker安装redis主从。这两个场景很有代表性前者涉及环境变量、数据卷和外部访问后者涉及Compose编排和集群配置。4.1 5分钟拉通MySQL 8.0并允许宿主机访问先拉镜像再写一个尽量完整的run命令docker pull mysql:8.0 docker run -d \ --name mysql8 \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORDYourStrongPass \ -e MYSQL_ROOT_HOST% \ -e TZAsia/Shanghai \ -v /data/mysql:/var/lib/mysql \ --restartalways \ mysql:8.0 \ --character-set-serverutf8mb4 \ --collation-serverutf8mb4_unicode_ci解释几个容易踩的细节。MYSQL_ROOT_HOST%让root用户允许从任意主机连接不加这个参数某些镜像版本里root会被限制只能localhost登录外部工具连不上。TZ设置容器时区为亚洲上海否则容器默认UTC日志时间和业务对不上。末尾的--character-set-serverutf8mb4和--collation-serverutf8mb4_unicode_ci是容器启动时传给MySQL的参数解决中文乱码。启动后先在宿主机测一下docker ps | grep mysql8 docker logs mysql8 | tail -n 20看到类似“ready for connections”的日志说明数据库起来了。再用宿主机上的客户端连mysql -h127.0.0.1 -P3306 -uroot -p从宿主机连接容器内的MySQL用的就是127.0.0.1加映射端口。如果你在服务器上部署外部客户端连的时候把127.0.0.1换成服务器公网IP或内网IP即可。很多人装完MySQL连不上排错顺序我建议是先docker ps看容器是不是活着再看docker logs mysql8有没有报错再看宿主机防火墙有没有放行3306端口最后才怀疑MySQL配置。顺序反了容易白折腾半天。4.2 用Compose编排Redis主从Redis主从是缓存场景里很常见的架构用Docker Compose可以在一个文件里把主从两个节点都定义好。我写一个简化版本version: 3.8 services: redis-master: image: redis:7.2-alpine container_name: redis-master command: redis-server --requirepass RedisMasterPass ports: - 6379:6379 volumes: - masterdata:/data restart: always redis-slave: image: redis:7.2-alpine container_name: redis-slave command: redis-server --replicaof redis-master 6379 --masterauth RedisMasterPass ports: - 6380:6379 volumes: - slavedata:/data restart: always depends_on: - redis-master volumes: masterdata: slavedata:启动docker compose up -d验证主从是否同步成功进从节点查状态docker exec -it redis-slave redis-cli -a RedisMasterPass info replication输出里看到role:slave和master_link_status:up说明主从链路没问题。这里有个很多人翻车的地方主节点设了密码requirepass从节点必须配masterauth否则主从连接时报NOAUTH Authentication required日志看起来像网络不通实际上是认证失败。Redis的--replicaof参数后面接的是容器名redis-master不是宿主机IP因为同一个Compose网络里容器名就是可解析的主机名。这套组合拳打下来你已经把镜像、容器、端口、数据卷、Compose全用了一遍。4.3 顺手解决一批“别人问烂了”的部署需求MySQL和Redis跑通之后其他部署就都是套模板了。GitLab装起来最让人意外的是内存需求官方推荐至少4GB内存小主机上硬跑会让整机卡死。命令本身很简单docker run -d \ --name gitlab \ -p 8443:443 -p 8081:80 \ -v /data/gitlab/config:/etc/gitlab \ -v /data/gitlab/logs:/var/log/gitlab \ -v /data/gitlab/data:/var/opt/gitlab \ gitlab/gitlab-ce:latestKodbox这种网盘类应用就轻多了docker run -d --name kodbox -p 8090:80 -v /data/kodbox:/var/www/html kodcloud/kodbox启动后浏览器访问http://IP:8090按安装向导走就行。Hadoop这类大数据组件用Docker跑通常是搭整套测试集群需要专门的大数据镜像和更大的内存16G以下建议别玩。人大金仓数据库也有官方镜像部署方式和MySQL类似主要区别是初始化库实例的方式拉下来之后按官方文档初始化实例即可不要直接跳过初始化就去连库。微服务项目更是Docker的主场每个模块打成一个镜像用Compose统一编排就是一套标准的容器化部署方案。5. 网安场景下的Docker实战Docker在网络安全领域的存在感越来越强。渗透测试要快速搭靶场恶意样本分析要隔离环境安全研发要跑漏洞扫描Docker都能帮忙。但这块也有安全红线我先划清楚所有测试必须在授权范围、隔离网络内进行不要拿Docker对着别人的线上系统乱扫乱打。我下面写的都是防御和合法自测场景。5.1 靶场五分钟上线DVWA加Kali攻击机DVWA是经典的Web漏洞靶场以前搭建要装Apache、MySQL、PHP手工配环境能折腾一小时。现在有现成的Docker镜像一条命令搞定docker run -d --name dvwa -p 8080:80 vulnerables/web-dvwa启动后浏览器访问http://IP:8080按提示初始化数据库默认账号密码是admin/password。靶场自带SQL注入、XSS、文件上传、CSRF等漏洞环境是合法的漏洞复现练习平台。如果你想配合Kali做测试可以拉一个Kali容器放到同一个网络里把DVWA当靶机docker pull kalilinux/kali-rolling docker run -it --network mynet kalilinux/kali-rolling bash在Kali容器里装需要的工具对dvwa容器地址做授权范围内的测试。这种模式的优点是一套环境用完即焚不污染宿主机重新拉个容器又是一条好汉。提示不要在靶场里使用真实IP、真实个人信息也不要开着公网映射做实验。任何时候先确认网络环境是不是隔离的。5.2 恶意样本容器化分析能用但别迷信Docker经常被用来做恶意样本的快速分析。思路很简单准备一个临时容器挂载样本目录跑一遍行为分析工具看它改了什么文件、连了哪些地址跑完直接删容器。一个常见的最小化启动命令docker run --rm -it \ --name sandbox \ --network none \ -v /tmp/samples:/samples:ro \ -v /tmp/logs:/logs \ ubuntu:22.04 bash这里有两个参数值得注意。--network none让容器断网防止样本在分析过程中回连或下载第二阶段载荷-v /tmp/samples:/samples:ro是只读挂载样本目录避免样本篡改分析环境。但我要泼一盆冷水Docker容器和宿主机共享内核恶意样本一旦尝试内核提权漏洞容器边界就不够用了。真正处理高威胁样本还是要用完整的虚拟机快照方案比如VirtualBox快照、专用沙箱。Docker适合的是低风险样本的日常快速分析它最大的优势不是安全而是环境重置成本低。这个定位一定要清楚。5.3 镜像供应链安全上线前的检查安全人员看Docker最先盯的往往是镜像里面有没有漏洞这就叫镜像供应链安全。很多人从Docker Hub随手拉一个镜像就上生产这是不小的风险。常规做法是用镜像漏洞扫描工具过一遍。以Trivy为例docker pull aquasec/trivy:latest docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \ aquasec/trivy image mysql:8.0扫描结果会列出镜像里的CVE漏洞及严重程度。这个工具也能扫描文件系统、Git仓库、K8s配置文件是容器安全赛道非常出名的开源工具。从部署层面还有几件值得做的事尽量不用latest标签上线前锁定精确版本号。容器内进程不要用root跑能指定低权限用户就指定比如--user 10001:10001。启动参数加--cap-dropALL再去掉容器需要的特定capability缩小内核攻击面。不需要写数据的容器加--read-only挂载只读根文件系统。这几条对普通开发和运维也适用。Docker方便但别把方便当安全。5.4 N100小主机扛20个容器的资源规划热搜词里有一条很有意思N100跑20个Docker。N100是Intel的低功耗四核处理器TDP只有6W常见于NAS和小主机。很多人拿它做家庭服务器跑青龙面板、Kodbox、Nginx、Redis、MySQL、监控服务动不动就规划二三十个容器。N100能跑20个容器吗能但前提是容器别太“重”。我实测下来要注意三件事。第一镜像尽量选Alpine版本。同一个Nginxnginx:alpine比nginx:latest小一多半运行时内存占用也更低。想要轻量镜像里不要塞一堆不用的构建工具。第二内存必须限制。Docker默认不限制容器内存某个容器一旦内存泄漏会把整台小主机拖死。建议给每个容器设定--memory上限比如docker run -d --name kodbox --memory 512m -p 8090:80 kodcloud/kodbox对于青龙这类定时脚本容器200到300MB一般够用MySQL这类数据库给1GB以上比较稳。第三日志要清理。容器默认会把标准输出日志无限累积时间长了占满磁盘小主机直接卡死。启动时带上日志限制--log-driver json-file --log-opt max-size10m --log-opt max-file3或者写到Compose文件里防止日志把磁盘撑爆。最后再用docker stats看一眼每个容器的实时CPU和内存你会发现Docker对资源的感知非常直观哪些容器吃内存多、哪些容器闲着一目了然。只要把镜像做小、资源做限、日志管好N100跑20个容器完全可以是常态。6. 高频问题排查速查这些问题我都被卡过最后一章把前面提到的和没提的常见问题集中整理成速查形式。这些都是我在不同机器、不同系统上真实遇到过的场景直接拿去对照用。6.1 启动失败类现象常见原因排查与解决Docker Desktop全报virtualisation support not detectedBIOS未开启虚拟化或第三方虚拟化软件冲突进BIOS开启Intel VT-x/SVM关闭VMware/VirtualBox的冲突服务启用WSL2并更新内核docker服务启动失败报Failed to start Docker Application Container Enginedaemon.json格式错误、配置了不存在的路径、SELinux干扰执行journalctl -u docker -n 50看具体日志用docker daemon --validate验证配置或运行dockerd --validate对应版本docker命令找不到安装未完成或PATH没配好Linux执行which docker确认Windows检查环境变量并重开终端Docker Desktop启动后一直卡在starting与Hyper-V冲突或WSL2版本过旧执行wsl --update重装Docker Desktop检查Windows功能里Hyper-V和虚拟机平台都开启6.2 网络与权限类权限问题前面说过最经典的是permission denied while trying to connect to the Docker daemon socket直接加docker组然后重登。网络问题我单独列几条现象常见原因排查与解决容器里访问外网不通宿主机iptables FORWARD策略禁止转发或内核未开启IP转发检查net.ipv4.ip_forward是否为1执行sysctl -w net.ipv4.ip_forward1并写入/etc/sysctl.conf容器之间互相ping不通两个容器不在同一个bridge网络docker network create mynet启动容器时加--network mynet容器能ping通宿主机但宿主机无法访问容器IP默认bridge模式下容器IP不可直接从宿主机访问用-p端口映射方式访问容器服务不要依赖容器内网IP从Windows/macOS访问宿主机上的容器服务失败防火墙拦截或端口没暴露检查Windows防火墙对端口放行确认docker ps里PORTS列有映射记录还有个细节容器内默认DNS配置在部分网络环境下不通可以在/etc/docker/daemon.json里加dns: [223.5.5.5, 8.8.8.8]然后重启Docker。6.3 容器内应用访问类现象常见原因排查与解决宿主机能访问容器内MySQL外部工具连不上防火墙/安全组拦截或root用户登录限制检查云服务器安全组和本地防火墙放行3306启动参数加MYSQL_ROOT_HOST%MySQL容器起来了但客户端报认证插件错误MySQL8默认用caching_sha2_password老客户端不支持把用户改为mysql_native_passwordALTER USER root% IDENTIFIED WITH mysql_native_password BY 密码;Redis主从状态显示down从节点连主节点要认证但没配masterauth从节点命令加--masterauth 主密码--requirepass和--masterauth要配套容器内时区不对镜像默认UTCdocker run加-e TZAsia/Shanghai或在Dockerfile里设置时区容器磁盘占满日志文件无限增长启动参数加--log-opt max-size10m --log-opt max-file3定期用docker system prune清理悬空镜像和停止容器docker system prune是个好东西一条命令把没用的停止容器、悬空镜像、悬空网络全清掉。但要注意它也会删掉未被使用且没挂载的构建缓存生产环境执行前先看一眼docker system df确认空间占用。这几张表整理得再全也覆盖不了所有环境差异。真遇到问题时我建议的排查顺序永远是先用docker ps -a和docker logs 容器名拿到一手信息再结合docker inspect 容器名看配置细节。日志是最诚实的最怕的是连日志都不看就猜。我用Docker也有几年了最大的体会是Docker真正的价值不是替你省去了安装软件的功夫而是把“环境”本身变成了可版本化、可交付的资源。开发、测试、生产之间少了很多“在我机器上是好的啊”的扯皮跑靶场、做分析时也能随时重建一片干净的环境。平时我习惯把所有常用服务维护成一份份Compose文件新机器只需装好Docker然后docker compose up -d整个工具箱就齐了。这个习惯推荐你也试试前期花点时间写配置文件后面能省下成倍的时间。