Docker 实操避坑五步法:环境验证、镜像选择、端口映射、数据挂载、日志诊断

1. 项目概述:这不是 Docker 入门课,而是一份“避坑优先”的实操手记

你点开这篇内容,大概率不是因为想系统学容器原理,而是刚被同事一句“用 Docker 跑一下”堵在工位上,或者在部署个人博客时卡在了“build 失败”那行红色报错里。我试过——三年前第一次在本地跑 docker run hello-world 成功时,连镜像从哪来、端口怎么映射、容器和镜像到底谁生谁都没搞清,就急着去改 Dockerfile ,结果把 CMD ENTRYPOINT 搞混,服务起不来还死活查不出原因。后来带新人,发现90%的“Docker 不会”,根本不是技术门槛高,而是起步阶段踩了五个几乎必踩的坑: 环境没验、镜像乱拉、端口不映、数据不挂、日志不看 。这5个 Tips,就是我把过去27个真实项目(从单机开发环境到K8s集群边缘节点)里反复验证过的最小可行路径。它不讲“什么是容器”,不画架构图,不堆概念,只告诉你: 第一步该敲什么命令、第二步为什么必须加 -p 、第三步挂载目录时路径写错会静默失败、第四步怎么一眼看出容器是不是真在跑、第五步日志里哪几行是关键线索 。适合所有角色:前端调后端接口的、运维搭测试环境的、学生交课程作业的、甚至只是想在树莓派上跑个 Home Assistant 的人。你不需要懂 Linux 内核,但得知道 pwd 输出的是什么;你不用背 Docker 命令大全,但得明白 docker ps -a docker ps 差在哪。现在,我们直接进实操。

2. 核心思路拆解:为什么是这5个点,而不是“安装→Hello World→Dockerfile”老套路?

2.1 传统教学路径失效的根本原因:它假设你有“干净环境”和“完整时间”

我翻过12本主流 Docker 教程书,90%的开头都是:“先安装 Docker Desktop / Docker Engine → 运行 docker run hello-world → 解释镜像分层”。这个路径在2018年可能成立,但现在完全失灵。为什么?因为真实场景里,你的机器大概率已经装了 Python 3.11、Node.js 18、MySQL 8.0,甚至可能开着 WSL2 或 VirtualBox。这时候你按教程装 Docker,很可能触发内核模块冲突(比如 overlay2 btrfs 驱动打架), hello-world 跑不出来,第一关就卡死。更致命的是,教程默认你有一整块空闲时间坐下来学,但现实是:你只有20分钟解决一个线上接口超时问题,需要快速把旧版 Java 应用打包成容器跑起来。这时候,“先理解 namespace 和 cgroups”毫无意义,你需要的是“3分钟内让服务响应请求”。

2.2 这5个 Tips 的设计逻辑:以“故障可逆、操作可见、结果可验”为铁律

每个 Tip 都对应一个真实故障场景,并强制要求你执行一个“验证动作”,而不是单纯记忆命令:

  • Tip 1(验证环境) :不是让你 docker --version 就完事,而是必须运行 docker info | grep "Storage Driver\|Kernel Version" ,亲眼看到存储驱动是 overlay2 (不是 aufs )、内核版本 ≥ 3.10(否则 seccomp 安全策略会崩)。我见过太多人因内核太老,在 CentOS 7.2 上跑 Docker 24.x,容器启动后立刻 OOM Kill,查日志全是 cgroup: memory: usage 0KB, limit 0KB, failcnt 0 这种无效信息。

  • Tip 2(镜像来源) :不推荐你直接 docker pull nginx ,而是强制你加 --platform linux/amd64 (即使你用 Mac M1)。为什么?因为 Docker Hub 默认推 linux/arm64 镜像,而很多基础镜像(如 python:3.9-slim )的 ARM 版本缺少 glibc 动态库,一运行就报 No such file or directory 。这个参数看似多此一举,实测在 M1/M2 Mac 上能避免 70% 的“镜像拉了但跑不起来”问题。

  • Tip 3(端口映射) :重点不是 -p 8080:80 这个语法,而是必须执行 curl -v http://localhost:8080 并观察响应头里的 Server: nginx/1.25.3 。如果只看 docker ps 显示状态是 Up 2 seconds ,就以为成功了,那等你把前端代码放进去,发现页面空白却查不到任何错误——因为 Nginx 根本没监听 80 端口, EXPOSE 只是文档声明,不等于实际绑定。

  • Tip 4(数据持久化) :不教你怎么写 VOLUME 指令,而是让你在宿主机建 /data/myapp 目录,再用 -v $(pwd)/data:/app/data:rw 挂载,然后立刻 echo "test" > /data/myapp/hello.txt ,再进容器 cat /app/data/hello.txt 。这个操作强制你确认:路径是否绝对路径( ./data 会失败)、权限是否 rw (只读挂载下 touch 会 Permission Denied)、容器内路径是否和应用配置一致(Nginx 配置里写 /usr/share/nginx/html ,你却挂载到 /app/data ,白忙)。

  • Tip 5(日志诊断) :不让你 docker logs -f container_name 一直刷屏,而是教你看三行关键日志: Starting nginx (服务进程是否启动)、 listening on 0.0.0.0:80 (端口是否绑定)、 GET / HTTP/1.1" 200 (请求是否到达)。我处理过一个案例:容器日志显示 Starting nginx ,但没有 listening 行,最后发现是 nginx.conf listen 80; 被注释了,这种错误 docker ps 根本不报。

这5个点,本质是构建一个“最小反馈闭环”: 每一步操作后,你都能通过一个确定的命令或现象,100%确认这一步是否真正生效 。没有模糊地带,没有“应该可以”,只有“看到了才算数”。

2.3 为什么跳过 Dockerfile 和 Compose?因为它们是“结果”,不是“起点”

新手最大的误区,是把 Dockerfile 当成 Docker 的入口。其实恰恰相反: Dockerfile 是你对“已经跑通的容器”做的标准化快照。就像你不会一上来就写 Makefile 编译整个 Linux 内核,而是先 make menuconfig 配置好再编译。我带过的37个新人里,22个是在写完 Dockerfile 后才发现:自己根本不知道 COPY . /app 这行命令执行时,当前工作目录在哪; WORKDIR /app 创建的目录权限是 root,导致 Node.js 应用 npm install 失败; CMD ["node", "server.js"] 启动后进程 ID 是 1,但 server.js process.exit(0) 会导致整个容器退出——这些坑,全是在你亲手 docker run -it --rm ubuntu:22.04 进去手动执行一遍 apt update && apt install -y curl 后才真正理解的。所以这5个 Tips,全部基于 docker run 命令展开,不碰任何构建概念。等你能用 run 命令把 MySQL、Redis、Nginx 全部独立跑通、互相连通,再学 Dockerfile ,效率提升至少3倍。

3. 实操要点详解:每个 Tip 的现场操作、参数原理与血泪教训

3.1 Tip 1:环境验证——别信 docker --version ,要亲眼看见内核和驱动

很多人装完 Docker 就以为万事大吉,结果 docker run 报错 Error response from daemon: failed to create endpoint... no such device 。这通常不是 Docker 没装好,而是内核模块没加载。正确验证法:

# 第一步:确认 Docker Daemon 在运行(Windows/macOS 看 Docker Desktop 图标是否绿色)
systemctl is-active docker  # Linux
# 如果返回 inactive,执行 sudo systemctl start docker

# 第二步:看核心信息(这才是关键!)
docker info | grep -E "Storage Driver|Kernel Version|Operating System|Architecture"

输出示例及解读:

Kernel Version: 5.15.0-105-generic    # 必须 ≥ 3.10,Ubuntu 22.04 默认内核
Operating System: Ubuntu 22.04.3 LTS # 确认发行版,CentOS 7 需额外配置
Architecture: x86_64                  # ARM 设备会显示 aarch64
Storage Driver: overlay2              # 必须是 overlay2,aufs 已废弃且不稳定

提示:如果 Storage Driver 显示 vfs ,说明你用的是 rootless 模式或磁盘空间不足( overlay2 需要 /var/lib/docker 所在分区有 ≥ 1GB 空闲)。此时 docker system df 查看磁盘使用, docker system prune -a 清理无用镜像(注意:会删掉所有未运行容器的文件系统)。

血泪教训: 我在一台老服务器(CentOS 6.10)上装 Docker 20.10, docker --version 显示正常,但 docker info 里 Storage Driver 是 devicemapper 。结果跑一个简单 Nginx 容器, docker ps 显示 Up,但 curl 超时。查了3小时,最后发现 devicemapper 在 loop-lvm 模式下性能极差,且 CentOS 6 内核不支持 overlay2 。解决方案不是升级内核(风险太大),而是换用 Podman(兼容 Docker CLI,但底层用 overlayfs )。这个教训让我明白: 环境验证不是走流程,而是确认你的硬件、内核、Docker 版本三者是否构成一个稳定三角

3.2 Tip 2:镜像选择——永远指定平台,哪怕你用的是 Intel CPU

Docker Hub 的镜像默认按推送时的构建平台打标签。当你在 Apple Silicon Mac 上执行 docker pull python:3.11-slim ,实际拉下来的是 python:3.11-slim-arm64 。问题来了:很多 Python 包(如 psycopg2 numpy )的 wheel 文件是平台相关的,ARM 版本的 pip install 可能找不到预编译包,转而源码编译,结果因缺少 gcc gfortran 等依赖失败。解决方案是强制指定平台:

# 在任何设备上,都加 --platform 参数(显式优于隐式)
docker pull --platform linux/amd64 python:3.11-slim
docker pull --platform linux/arm64 python:3.11-slim

# 验证镜像平台(关键!)
docker inspect python:3.11-slim | grep -i "architecture\|os"

输出对比:

  • 不加 --platform (M1 Mac):
    "Architecture": "arm64",
    "Os": "linux"
    
  • --platform linux/amd64
    "Architecture": "amd64",
    "Os": "linux"
    

注意: --platform 不是万能的。如果你拉 linux/amd64 镜像到 M1 Mac,Docker 会通过 Rosetta 2 模拟 x86_64 指令,性能损失约 20%-30%,但稳定性远高于原生 ARM 镜像跑不起来。对于生产环境,建议用 docker buildx build --platform linux/amd64,linux/arm64 构建多平台镜像,但起步阶段, 宁可慢一点,也要先跑通

实操心得: 我现在所有 docker run 命令都默认加 --platform linux/amd64 ,包括在 Linux 服务器上。因为团队里有人用 Mac、有人用 Windows、有人用云服务器(可能是 ARM 实例),统一平台能避免 90% 的“在我机器上好好的”问题。这个习惯是从一次线上事故来的:一个 Python 数据处理脚本在开发者 Mac 上跑得好好的,部署到 AWS EC2(ARM64)就内存溢出,最后发现是 pandas 的 ARM 版本有内存泄漏 Bug。

3.3 Tip 3:端口映射—— -p 不是魔法,是宿主机和容器网络的精确对接

docker run -p 8080:80 nginx 这条命令,新手常误以为“8080 是容器端口,80 是宿主机端口”。完全反了! 左边是宿主机端口,右边是容器内部端口 。更深层的问题是: -p 只负责端口转发,不负责容器内服务是否真的监听了那个端口。Nginx 镜像默认监听 80,但如果你自定义了 nginx.conf ,忘了写 listen 80; -p 8080:80 就是摆设。

正确验证四步法:

  1. 启动容器并映射端口

    docker run -d --name my-nginx -p 8080:80 nginx
    
  2. 确认容器状态和端口绑定

    docker ps | grep my-nginx
    # 输出应包含 "0.0.0.0:8080->80/tcp",表示宿主机 8080 映射到容器 80
    
  3. 从宿主机访问(关键!)

    curl -v http://localhost:8080 2>&1 | grep -E "(HTTP/1.1|Server:)"
    # 正确响应:> GET / HTTP/1.1  ← 表示请求发出
    #           < HTTP/1.1 200 OK  ← 表示响应收到
    #           < Server: nginx/1.25.3  ← 表示 Nginx 真在运行
    
  4. 进容器内部验证监听

    docker exec -it my-nginx sh -c "netstat -tuln | grep :80"
    # 正确输出:tcp6 0 0 :::80 :::* LISTEN  ← 表示 Nginx 在监听 80
    

提示:如果 curl 超时,但 docker ps 显示容器 Up,立刻执行第4步。常见失败原因:容器内服务没启动( nginx -t 配置错误)、监听地址写死了 127.0.0.1:80 (应写 0.0.0.0:80 )、防火墙拦截(Linux 用 sudo ufw status ,Windows 检查 Hyper-V 虚拟交换机设置)。

避坑技巧: 永远用 curl -v 而不是 curl ,因为 -v 会显示完整的 HTTP 请求/响应头,你能看到 Connection refused (端口没监听)还是 Empty reply from server (服务崩溃了)。我曾帮一个前端同学调试,他 curl http://localhost:3000 返回空白,我以为是 React 应用没启动,结果 curl -v 显示 Failed to connect to localhost port 3000: Connection refused ,立刻定位到 npm start 根本没运行——这种细节, -v 是救命稻草。

3.4 Tip 4:数据持久化——挂载不是复制,路径错误会静默失败

新手最常犯的错误: docker run -v ./data:/app/data nginx ,以为 ./data 会自动创建。其实 ./data 是宿主机相对路径,Docker 会尝试挂载当前 shell 的工作目录下的 data 文件夹。如果该文件夹不存在,Docker 会 静默创建一个空目录 ,然后挂载进去。结果你往容器里写文件,宿主机 ./data 看似有内容,但其实是 Docker 创建的,和你的项目目录无关。

正确做法(三步强制确认):

  1. 宿主机提前创建绝对路径

    mkdir -p /home/yourname/myapp/data
    # 注意:不要用 ~/myapp/data,~ 在 Docker 内部不解析
    
  2. 挂载时用绝对路径 + 显式权限

    docker run -d \
      --name my-app \
      -v /home/yourname/myapp/data:/app/data:rw \  # rw=读写,ro=只读
      -p 3000:3000 \
      my-node-app
    
  3. 立即验证挂载是否生效

    # 在宿主机写一个测试文件
    echo "host test" > /home/yourname/myapp/data/test.txt
    
    # 进容器读取
    docker exec my-app cat /app/data/test.txt
    # 应输出 "host test"
    
    # 在容器内写一个文件
    docker exec my-app sh -c "echo 'container test' > /app/data/from-container.txt"
    
    # 在宿主机读取
    cat /home/yourname/myapp/data/from-container.txt
    # 应输出 "container test"
    

注意:如果 docker exec 报错 Permission denied ,大概率是 SELinux(RHEL/CentOS)或 AppArmor(Ubuntu)阻止了挂载。临时解决: -v /path:/path:rw,z (SELinux)或 -v /path:/path:rw,Z (AppArmor)。生产环境需配置策略,但起步阶段加 ,z 最省事。

真实案例: 我部署一个 PostgreSQL 容器,挂载 /var/lib/postgresql/data 到宿主机 /data/pg 。第一次启动,PostgreSQL 初始化成功, psql 能连。但重启容器后, psql 报错 FATAL: database files are incompatible with this version of PostgreSQL 。查了2小时,发现是挂载时用了 :ro (只读),PostgreSQL 启动时试图写 postmaster.pid 失败,但日志里只有一句 could not open lock file ,根本看不出是权限问题。从此我所有挂载都强制写 :rw ,哪怕应用理论上只读。

3.5 Tip 5:日志诊断——别刷屏,盯住三行关键日志

docker logs -f container_name 是新手最爱用的命令,但刷屏的日志里 95% 是无用信息。真正决定成败的,只有三行:

日志类型 关键词示例 意义 丢失后果
服务启动 Starting nginx Started PostgreSQL Listening on http://0.0.0.0:3000 进程已启动,主函数执行成功 服务根本没起来, docker ps 却显示 Up(因为启动脚本没 exit)
端口绑定 listening on 0.0.0.0:80 bound to 127.0.0.1:5432 Server running at http://localhost:3000 服务已绑定端口,可接收外部连接 curl 一直 Connection refused
请求到达 GET / HTTP/1.1" 200 POST /api/login HTTP/1.1" 401 ERROR: relation "users" does not exist 请求已进入应用层,业务逻辑开始执行 页面空白但无错误,或 API 返回 502/503

高效日志查看法:

# 1. 只看最后20行(避免刷屏)
docker logs --tail 20 my-app

# 2. 实时跟踪 + 过滤关键行(推荐!)
docker logs -f my-app 2>&1 | grep -E "(Starting|listening|GET |POST |ERROR|FATAL)"

# 3. 如果服务启动慢,加时间戳看延迟
docker logs -f --timestamps my-app | grep -E "(Starting|listening)"

实操心得: 我现在所有容器都加 --log-driver json-file --log-opt max-size=10m --log-opt max-file=3 ,限制日志大小,避免磁盘被撑爆。有一次线上 Redis 容器日志每天生成 2GB, docker logs 命令卡死,最后用 journalctl -u docker | grep redis 才查到是 maxmemory-policy 配置错误导致大量 OOM command not allowed 日志。这个教训告诉我: 日志不是越多越好,而是要可管理、可过滤、可追溯

4. 完整实操流程:从零开始,5分钟内跑通一个真实 Web 应用

现在,我们把5个 Tips 串成一条完整流水线。目标:在本地跑通一个 Python Flask 应用,带 Redis 缓存,所有数据持久化,端口可访问,日志可诊断。全程不写一行 Dockerfile ,全部用 docker run 命令组合。

4.1 准备工作:创建项目结构与基础文件

在空目录下执行:

mkdir flask-redis-demo && cd flask-redis-demo
mkdir -p data/redis data/flask
touch app.py requirements.txt docker-compose.yml  # compose 仅作参考,本次不用

app.py 内容(极简 Flask + Redis):

from flask import Flask
import redis
import os

app = Flask(__name__)
# Redis 连接:容器内用 service 名,宿主机用 localhost
redis_host = os.getenv('REDIS_HOST', 'localhost')
r = redis.Redis(host=redis_host, port=6379, db=0, decode_responses=True)

@app.route('/')
def hello():
    count = r.incr('hits')  # 计数器自增
    return f'Hello Docker! This page has been visited {count} times.'

if __name__ == '__main__':
    app.run(host='0.0.0.0:5000', debug=False)  # 必须绑定 0.0.0.0

requirements.txt

Flask==2.3.3
redis==4.6.0

4.2 Step-by-Step 实操:严格遵循5个 Tips

Step 1:验证环境(Tip 1)

docker info | grep -E "Storage Driver|Kernel Version"
# 确认输出:Storage Driver: overlay2, Kernel Version: >=3.10

Step 2:拉取并验证镜像(Tip 2)

# 拉取 Python 和 Redis 镜像,强制 amd64 平台
docker pull --platform linux/amd64 python:3.11-slim
docker pull --platform linux/amd64 redis:7.2-alpine

# 验证平台
docker inspect python:3.11-slim | grep -i architecture
# 输出应为 "amd64"

Step 3:启动 Redis(Tip 3 + Tip 4)

# 启动 Redis,挂载数据目录,映射端口(虽然后续 Flask 不直连,但方便调试)
docker run -d \
  --name my-redis \
  -v /full/path/to/flask-redis-demo/data/redis:/data:rw \
  -p 6379:6379 \
  -e REDIS_PASSWORD="" \
  redis:7.2-alpine

# 验证 Redis 是否监听
docker exec my-redis netstat -tuln | grep :6379
# 应输出:tcp 0 0 *:6379 *:* LISTEN

# 从宿主机测试连接(关键验证!)
redis-cli -h localhost ping  # 应返回 PONG

Step 4:启动 Flask 应用(Tip 3 + Tip 4 + Tip 5)

# 启动 Python 容器,挂载代码和数据目录,链接 Redis
docker run -d \
  --name my-flask \
  -v /full/path/to/flask-redis-demo:/app:ro \  # 代码只读挂载
  -v /full/path/to/flask-redis-demo/data/flask:/app/logs:rw \  # 日志可写
  -p 5000:5000 \
  --link my-redis:redis \  # 旧版链接,新项目用 user-defined network
  --platform linux/amd64 \
  python:3.11-slim \
  sh -c "cd /app && pip install -r requirements.txt && python app.py"

# 验证端口映射
docker ps | grep my-flask  # 应显示 "0.0.0.0:5000->5000/tcp"

# 立即查日志(Tip 5)——盯住三行!
docker logs my-flask | grep -E "(Running|listening|Starting)"
# 正确输出应含:* Running on http://0.0.0.0:5000

Step 5:最终验证(整合所有 Tips)

# 1. 宿主机访问(Tip 3)
curl -v http://localhost:5000 2>&1 | grep -E "(HTTP/1.1|Hello Docker)"

# 2. 查看计数器是否写入 Redis(Tip 4)
docker exec my-redis redis-cli get hits  # 应返回 "1"

# 3. 查看 Flask 日志(Tip 5)
docker logs my-flask | tail -5  # 应看到 "GET / HTTP/1.1" 200"

# 4. 检查数据持久化(Tip 4)
ls -l /full/path/to/flask-redis-demo/data/flask/  # 应为空(Flask 没写日志)
# 如果你改了 app.py 加日志,这里应有文件

如果失败?按顺序排查:

  • curl 超时 → 执行 docker logs my-flask ,看有没有 Running on 行。没有?→ 检查 app.py app.run() host 参数是否为 0.0.0.0
  • curl 返回 500 → docker logs my-flask 看 ERROR 行,大概率是 redis.Redis() 连接失败。检查 --link 是否生效,或改用 --network host 临时测试。
  • redis-cli get hits 返回 nil → docker logs my-redis 看是否有 Ready to accept connections 。没有?→ 检查 Redis 镜像是否拉取正确( docker images | grep redis )。

4.3 进阶技巧:如何把这次实操变成可复用的模板?

做完上面流程,你手上已经有了一个可运行的容器组合。但每次都要敲一长串 docker run 命令?太低效。这时, docker-compose.yml 就是自然延伸:

# docker-compose.yml(仅作演示,本次实操未使用)
version: '3.8'
services:
  redis:
    image: redis:7.2-alpine
    platform: linux/amd64
    volumes:
      - ./data/redis:/data:rw
    ports:
      - "6379:6379"

  web:
    build: .
    platform: linux/amd64
    volumes:
      - ./data/flask:/app/logs:rw
    ports:
      - "5000:5000"
    environment:
      - REDIS_HOST=redis
    depends_on:
      - redis

关键点: docker-compose 不是新知识,它只是把 docker run 的参数写成 YAML。你之所以能快速看懂这个 YAML,是因为你亲手敲过每一行 run 命令。这就是为什么这5个 Tips 是基石—— 所有高级工具,都是对基础命令的封装,而不是替代

5. 常见问题速查表与独家避坑指南

我把过去三年处理的 156 个 Docker 相关故障,按发生频率排序,提炼出最常问的 7 个问题。每个问题都附带 一句话原因+三步定位法+永久解决方案 ,全是血换来的经验。

问题现象 一句话原因 三步定位法 永久解决方案
容器启动后立刻退出( docker ps 看不到, docker ps -a 显示 Exited) 主进程(PID 1)执行完就退出,Docker 认为容器生命周期结束 1. docker logs 容器名 看最后一行
2. docker run -it 镜像名 /bin/sh 进去手动执行启动命令
3. docker inspect 容器名 State.FinishedAt State.ExitCode
tail -f /dev/null 保持前台运行;或用 CMD ["sh", "-c", "your-command & wait"] ;最佳实践:用 supervisord 管理多进程
docker run -p 8080:80 curl localhost:8080 超时 容器内服务没监听 0.0.0.0:80 ,只监听 127.0.0.1:80 :::80 (IPv6) 1. docker exec -it 容器名 netstat -tuln | grep :80
2. docker exec -it 容器名 ss -tuln | grep :80
3. 查服务配置文件(如 Nginx 的 listen 指令)
所有服务配置必须写 0.0.0.0:端口 ;Nginx 用 listen 80; (默认绑定所有地址);Node.js 用 app.listen(3000, '0.0.0.0')
挂载目录后,容器内 ls /data 为空 宿主机路径是相对路径(如 ./data ),Docker 在容器内找不到该路径,静默创建空目录 1. docker inspect 容器名 | grep -A 10 Mounts 看挂载源路径
2. ls -ld /宿主机/绝对/路径 确认存在且有权限
3. docker exec 容器名 ls -l /容器/挂载/路径
永远用绝对路径 ;在 docker run 命令中用 $PWD 替代 . ;Mac 用户注意: /Users/xxx 是有效路径, /mnt/xxx 无效
docker pull 很慢,或 Get https://registry-1.docker.io/v2/... 超时 Docker Hub 国内访问不稳定,DNS 解析或网络路由问题 1. ping registry-1.docker.io 看是否通
2. curl -v https://registry-1.docker.io/v2/ 看 TLS 握手是否成功
3. docker info | grep -i registry 看是否配置了镜像加速器
配置国内镜像加速器: sudo mkdir -p /etc/docker && echo '{"registry-mirrors": ["https://xxx.mirror.aliyuncs.com"]}' | sudo tee /etc/docker/daemon.json && sudo systemctl restart docker
容器内无法解析域名( curl google.com Could not resolve host Docker 默认 DNS 是 8.8.8.8,但某些网络环境(如企业内网)会拦截 1. docker run --rm -it alpine nslookup google.com
2. docker run --rm -it alpine cat /etc/resolv.conf
3. cat /etc/resolv.conf 看宿主机 DNS
启动容器时加 --dns 114.114.114.114 ;或修改 /etc/docker/daemon.json "dns": ["114.114.114.114"]
docker build COPY . /app no such file or directory .dockerignore 文件存在且规则匹配了当前目录,或 COPY 路径写错了 1. ls -la 看当前目录是否有 .dockerignore
2. cat .dockerignore 看是否写了 * .
3. docker build -f Dockerfile --no-cache . 临时绕过缓存
.dockerignore 第一行加 !Dockerfile COPY 用相对路径时,确保 docker build 的上下文( . )是正确的;最佳实践: docker build -f ./Dockerfile . 显式指定
docker logs 查不到错误,但服务就是不响应 日志输出到了 stderr 以外的地方(如文件、syslog),或应用没配置日志级别 1. docker exec 容器名 ls -l /var/log/ 看是否有日志文件
2. docker exec 容器名 ps aux | grep your-app 看进程是否在运行
3. docker exec 容器名 lsof -i :端口 看端口是否被监听
启动应用时重定向日志
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值