一场史诗级的冒险——Docker命令大航海!
各位亲爱的开发者、运维勇士、以及所有对现代化软件部署充满好奇的小伙伴们!今天,我们将开启一场史诗级的冒险——Docker命令大航海!我们将乘坐“Docker号”巨轮,驶向容器化技术的星辰大海。
这不是一篇枯燥的说明书,而是一份充满活力、深入浅出、甚至有点好玩的终极指南。我们将用超过30000字的篇幅,把Docker的常用命令掰开了、揉碎了,配上生动的比喻、实战的场景、以及那些官方文档可能没告诉你的“骚操作”和“坑爹陷阱”,让你不仅看得明白,更能用得潇洒。
准备好了吗?系好安全带,我们的Docker奇幻之旅,正式起航!
<摘要>
Docker,这个席卷全球的容器化技术,早已不是运维的专属玩具,而是每一位现代开发者必须掌握的利器。本文将以一场趣味横生的“大航海”为主题,将Docker的核心概念化为海洋与船只,系统性地解析其最常用、最核心的命令。从最基本的docker run
启航,到复杂多容器编排的docker compose
远征;从镜像构建的docker build
造船厂,到网络与数据管理的港口与仓库。我们将不仅讲解命令的语法,更深入剖析其背后的原理、使用场景、最佳实践以及常见陷阱。本文旨在成为一份集教程、手册、秘籍于一体的终极指南,让读者在轻松愉快的阅读中,真正掌握Docker的强大力量,成为一名自信的“容器船长”。
<解析>
第一章:起锚!—— Docker基础与安装验证
在我们开始指挥(输入命令)之前,得先确保我们的“船长室”(命令行终端)和“Docker引擎”都准备就绪。
1.1 世界观设定:容器 vs 虚拟机
想象一下,你要运送一批玩具。
- 虚拟机 (Virtual Machine):相当于买了几台全新的大卡车,每台卡车上都要安装一个完整的操作系统(司机、发动机、油箱一应俱全),然后再把玩具和玩具的运行环境(比如一个小架子)放进去。笨重、耗油(资源)、启动慢。
- 容器 (Container):相当于使用了标准化集装箱。所有玩具和它需要的小架子都打包在一个集装箱里。这个集装箱可以放在任何一艘大船(主机操作系统) 上,由船上的统一引擎(Docker Engine)来管理和运输。轻便、高效、秒级启动。
Docker就是这套集装箱系统的发明者和标准制定者。 它包含了:
- Docker Daemon ( dockerd ): 船的引擎室,常驻后台的核心程序,负责干重活(构建、运行、分发容器)。
- Docker Client ( docker ): 船长的对讲机,我们通过它向引擎室发送命令。
- Docker Registry: 世界的集装箱仓库(比如最大的公共仓库 Docker Hub),用于存储和分享镜像。
- Image: 集装箱的蓝图。它是一个只读的模板,包含了运行所需的一切:代码、运行时、库、环境变量等。
- Container: 根据蓝图实例化出来的、正在运行的集装箱。蓝图是静态的,容器是动态的。
1.2 安装Docker引擎
不同的操作系统,安装方式不同。我们的“Docker号”巨轮需要在不同的海域(系统)中航行。
-
Linux (Ubuntu/CentOS): 通常通过官方源安装,过程最纯粹。
# Ubuntu 示例 sudo apt-get update sudo apt-get install docker.io # 或者使用官方安装脚本(总是获取最新版) curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh
-
macOS / Windows: 下载并安装 Docker Desktop。这是一个“全家桶”,包含了Docker引擎、客户端、图形化界面、以及必需的Linux虚拟机(因为Mac/Windows内核不是Linux,需要一个小型VM来运行容器)。安装后,一个可爱的鲸鱼图标会出现在你的状态栏。
1.3 验证安装与Hello World
安装完成后,打开你的终端(对讲机),喊出你的第一道命令:
docker --version
如果安装成功,它会告诉你Docker的版本号,证明“对讲机”和“引擎室”连接正常。
接下来,让我们拉起第一个集装箱,一个最经典的“Hello World”:
docker run hello-world
发生了什么?魔法!
docker
: 你拿起了对讲机。run
: 你下达了“运行”的指令。hello-world
: 你要运行的集装箱蓝图(镜像)的名字。- 执行流程:
- 船长(Client)通过对讲机告诉引擎室(Daemon):“我们要运行
hello-world
!” - 引擎室一看,本地仓库没有名叫
hello-world
的蓝图(镜像)。 - 引擎室立刻联系远方的公共仓库(Docker Hub):“嘿,给我一份
hello-world
的蓝图!” - 仓库把蓝图下载到本地(
Pull complete
)。 - 引擎室根据蓝图,制造并启动一个集装箱(容器)。
- 这个集装箱里只有一个简单的程序,它的任务就是打印出一段欢迎信息和一些学习资料,然后任务完成,集装箱停止运行。
- 船长(Client)通过对讲机告诉引擎室(Daemon):“我们要运行
恭喜你,你已经成功运行了第一个Docker容器!你已经成为了一名见习水手!
第二章:造船厂与蓝图库 —— 镜像(Image)管理命令
镜像(Image)是容器的基础。就像没有蓝图造不出集装箱一样,没有镜像也跑不起容器。这一章,我们学习如何获取、查看、制作和管理这些宝贵的“蓝图”。
2.1 docker search
- 在仓库里搜寻蓝图
在建造之前,我们先看看仓库里有没有现成的、别人已经做好的蓝图。
docker search [OPTIONS] TERM
- 例子:我想找一个Nginx(一个流行的Web服务器)的镜像。
docker search nginx
- 输出解读:
NAME
: 镜像的名字。DESCRIPTION
: 简要描述。STARS
: 星星数,类似于GitHub的Star,代表受欢迎程度。OFFICIAL
:[OK]
表示是官方镜像,由Docker官方或项目原团队维护,通常最可靠。AUTOMATED
: 表示是自动构建的,通常由Docker Hub链接GitHub仓库自动生成镜像。
- 常用选项:
--filter is-official=true
: 只显示官方镜像。--limit 5
: 只显示前5个结果。
2.2 docker pull
- 下载蓝图到本地船厂
docker run
会自动下载不存在的镜像,但有时我们想提前下载好,比如为了预缓存或确保版本一致。
docker pull [OPTIONS] NAME[:TAG|@DIGEST]
- 镜像名与标签(TAG): 镜像名通常由
[仓库URL/]用户名/镜像名
组成。如果不指定用户名和仓库URL,默认从Docker Hub拉取。nginx
-> 等价于library/nginx
(Docker Hub官方库)bitnami/nginx
-> Docker Hub上bitnami
用户发布的nginx
镜像harbor.mycompany.com:5000/myapp:v1.2
-> 从私有仓库harbor.mycompany.com:5000
拉取myapp
镜像的v1.2
版本
- 标签(TAG): 相当于蓝图的版本号。如果不指定,默认使用
:latest
标签。:latest
: 并不一定代表“最新”,它只是一个默认标签名。在生产环境中永远不要使用:latest
,因为它今天和明天拉取的可能是不同的版本,导致环境不一致。- 明确版本:
:1.21
,:1.21-alpine
,:v2.1.0
- 系统变体:
-alpine
(基于极小的Alpine Linux系统),-slim
,-buster
(基于Debian)
- 例子:
docker pull nginx:1.21-alpine # 拉取一个特定版本、轻量级的Nginx docker pull ubuntu:20.04 # 拉取Ubuntu 20.04的基础镜像 docker pull mysql:8.0 # 拉取MySQL 8.0系列的最新版本
2.3 docker images
- 查看本地船厂里的所有蓝图
下载了那么多镜像,怎么查看我本地都有啥呢?
docker images [OPTIONS] [REPOSITORY[:TAG]]
- 例子:
docker images
- 输出解读:
REPOSITORY
: 镜像仓库源(名字)。TAG
: 标签。IMAGE ID
: 镜像的唯一ID(摘要),是镜像的唯一标识。CREATED
: 创建时间。SIZE
: 镜像大小。
- 常用选项:
-q, --quiet
: 只显示镜像的ID。这在写脚本时非常有用。docker images -q # 输出: 1a184f6f0f3a # d434d6d5e5b2
--format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}"
: 用Go模板自定义输出格式。--filter dangling=true
: 显示悬虚镜像(后面会讲)。
2.4 docker rmi
- 拆除废弃的蓝图
本地磁盘空间是宝贵的,需要定期清理不用的镜像。
docker rmi [OPTIONS] IMAGE [IMAGE...]
- 例子:
docker rmi nginx:1.21-alpine # 删除指定标签的镜像 docker rmi 1a184f6f0f3a # 通过ID删除,可以只写ID的前几位,只要能唯一区分即可 docker rmi $(docker images -q) # 危险!删除所有镜像!$(...)是命令替换,先执行里面的命令
- 注意: 如果一个镜像有多个标签,
docker rmi
只是删除指定的标签。只有当最后一个标签被删除时,镜像本身才会被真正删除。如果镜像正在被容器使用,则需要先删除容器才能删除镜像。 - 常用选项:
-f, --force
: 强制删除,即使有容器正在使用它(不推荐,可能导致“悬虚容器”)。
2.5 docker build
- 自己动手,绘制蓝图
最强大的部分来了!我们不能总是用别人的蓝图,我们要学会自己制作。
docker build
命令用于从一个 Dockerfile
文件构建镜像。Dockerfile
是一个文本文件,里面包含了一条条指令,告诉Docker如何一步步构建我们的镜像。
一个简单的Dockerfile示例:
# 使用官方的Python轻量级镜像作为蓝图的基础
FROM python:3.9-alpine# 在容器内设置工作目录
WORKDIR /app# 将当前目录下的所有文件复制到容器的 /app 目录下
COPY . .# 安装项目所需的依赖
RUN pip install -r requirements.txt# 告诉Docker,当容器启动时,运行这个命令
CMD ["python", "app.py"]
构建命令:
docker build [OPTIONS] PATH | URL | -
PATH
: 构建上下文路径。Docker会把PATH
下的所有文件打包发送给Docker引擎(所以不要在PATH
下放无关文件,用.dockerignore
过滤)。通常使用当前目录.
。- 例子:
# 在当前目录(包含Dockerfile)构建镜像,并命名为my-python-app:v1.0 docker build -t my-python-app:v1.0 .# 从Git仓库构建 docker build -t my-app https://github.com/user/repo.git#branch:subdir# 使用不同的Dockerfile文件构建 docker build -f Dockerfile.prod -t my-app:prod .
- 常用选项:
-t, --tag list
: 为镜像打标签,格式是name:tag
。-f, --file string
: 指定要使用的Dockerfile路径(默认是PATH/Dockerfile
)。--no-cache
: 构建时不使用缓存,从头开始每一步。常用于确保依赖的最新版本。--build-arg
: 设置构建时的变量。
2.6 docker image prune
- 船厂大扫除
清理那些不再使用的镜像,释放磁盘空间。
docker image prune [OPTIONS]
- 例子:
docker image prune # 交互式地删除所有悬虚镜像 docker image prune -a # 删除所有未被任何容器使用的镜像(危险!) docker image prune -a --filter "until=24h" # 删除24小时前创建的、未使用的镜像
- 悬虚镜像 (Dangling Images): 指的是没有标签的镜像,通常是构建新镜像时产生的旧层。它们通常可以被安全地清理掉。
第三章:扬帆!—— 容器(Container)生命周期管理命令
有了蓝图(镜像),我们就可以制造和运行集装箱(容器)了!这是最核心、最常用的部分。
3.1 docker run
- 制造并启航一个集装箱!
这是最最最核心的命令。它从一个镜像创建并启动一个容器。
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
选项多如牛毛,我们分类讲解:
A. 基础运行模式:
-d, --detach
: 后台运行。让容器在后台以“守护进程”模式运行。否则容器会占据你的终端(前台运行)。docker run -d nginx:alpine # 在后台启动一个Nginx
-it
: 交互式终端。这是两个选项的组合-i
(保持标准输入打开) 和-t
(分配一个伪终端)。这让你可以进入容器内部,与它的Shell进行交互。通常用于运行/bin/bash
或/bin/sh
。docker run -it ubuntu:20.04 /bin/bash # 启动一个Ubuntu容器并进入它的bash shell # 你现在就在容器内部了!可以执行ls, pwd, apt-get等命令 # 输入 exit 可以退出并停止容器
--rm
: 容器停止后自动删除。非常适合做临时测试,避免产生一堆停止的容器垃圾。docker run --rm -it alpine /bin/sh # 运行一个Alpine容器,退出后自动删除它
B. 命名与标识:
--name string
: 给容器起一个名字。如果不指定,Docker会随机分配一个有趣的名字(如angry_borg
,sleepy_turing
)。起名字后更容易管理。docker run -d --name my_webserver nginx:alpine
C. 网络与端口映射(非常重要!):
默认情况下,容器内的网络是与外界隔离的。我们需要手动“挖洞”,把容器内的端口映射到宿主机的端口上。
-p, --publish list
: 端口映射。格式是[主机IP:][主机端口:]容器端口
。docker run -d -p 80:80 nginx:alpine # 将容器的80端口映射到宿主机的80端口 # 现在访问 http://localhost 就能看到Nginx欢迎页docker run -d -p 8080:80 nginx:alpine # 将容器的80端口映射到宿主机的8080端口 # 访问 http://localhost:8080docker run -d -p 127.0.0.1:3306:3306 mysql:8.0 # 将容器的3306端口映射到宿主机的127.0.0.1的3306端口(只能本机访问)
--network string
: 连接网络。默认连接到bridge
网络(桥接网络)。可以连接到自定义网络以实现容器间通过容器名通信。docker run -d --network my-network --name web nginx:alpine
D. 数据持久化(Volume Mount & Bind Mount):
容器内的文件是临时的,容器一删除,文件就没了。我们必须把重要数据(如数据库文件、日志、配置文件)存到容器外部。
-v, --volume list
: 挂载卷。格式是[主机路径:][容器路径:][模式]
。这是最重要的数据持久化方式!- 匿名卷(Anonymous Volume): 只写容器路径。Docker会自动在主机上创建一个随机目录来挂载。
docker run -d -v /var/lib/mysql mysql:8.0 # MySQL数据存到匿名卷
- 命名卷(Named Volume): 使用卷名。需要先用
docker volume create
创建,或者Docker会自动创建。管理更方便,推荐方式。docker run -d -v mysql_data:/var/lib/mysql mysql:8.0
- 绑定挂载(Bind Mount): 直接指定主机路径。用于开发时同步代码,或者使用主机上的特定配置文件。
# 开发场景:将主机当前目录代码挂载到容器中,实现代码实时同步 docker run -d -v $(pwd):/app my-python-app# 配置挂载:使用主机上的nginx.conf覆盖容器内的默认配置 docker run -d -v /path/on/host/nginx.conf:/etc/nginx/nginx.conf nginx:alpine
- 匿名卷(Anonymous Volume): 只写容器路径。Docker会自动在主机上创建一个随机目录来挂载。
E. 环境变量:
-e, --env list
: 设置环境变量。许多镜像通过环境变量来配置。# 启动MySQL并设置root密码 docker run -d --name mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw mysql:8.0# 启动一个Web应用,设置运行环境为生产环境 docker run -d -e NODE_ENV=production my-node-app
一个综合性的docker run
例子:
docker run -d \ # 后台运行--name my_app \ # 容器名叫my_app-p 8080:3000 \ # 映射主机8080到容器3000端口-v app_data:/usr/src/app/data \ # 挂载命名卷用于数据持久化-e DATABASE_URL=postgresql://... \ # 设置数据库连接字符串--network my_bridge_network \ # 连接到自定义网络my-app:prod # 使用的镜像
3.2 docker ps
- 查看正在航行的集装箱
docker ps
用于列出当前正在运行的容器。
docker ps [OPTIONS]
- 例子:
docker ps # 查看正在运行的容器 docker ps -a # 查看所有容器(包括已停止的)
- 输出解读:
CONTAINER ID
: 容器的唯一短ID。IMAGE
: 使用的镜像。COMMAND
: 容器启动时运行的命令。CREATED
: 创建时间。STATUS
: 状态(Up 5 minutes: 运行了5分钟; Exited (0) 2 days ago: 2天前退出,退出码为0)。PORTS
: 端口映射情况。NAMES
: 容器名。
- 常用选项:
-a, --all
: 显示所有容器(默认只显示运行的)。-q, --quiet
: 只显示容器ID。-f, --filter
: 按条件过滤。docker ps -f name=my_ # 查找名字包含`my_`的容器 docker ps -f status=exited # 查找已停止的容器 docker ps -f ancestor=nginx # 查找由Nginx镜像创建的容器
3.3 docker stop
/ docker start
/ docker restart
- 暂停与重启集装箱
docker stop [OPTIONS] CONTAINER [CONTAINER...]
: 停止一个或多个运行中的容器。发送SIGTERM信号,允许容器优雅地关闭。docker stop my_webserver docker stop 1a184f6f0f3a
docker start [OPTIONS] CONTAINER [CONTAINER...]
: 启动一个或多个已停止的容器。它会保留容器第一次运行时的所有参数。docker start my_webserver
docker restart [OPTIONS] CONTAINER [CONTAINER...]
: 重启容器。相当于stop
后再start
。docker restart my_webserver
3.4 docker rm
- 拆除已停泊的集装箱
删除已停止的容器,释放资源。
docker rm [OPTIONS] CONTAINER [CONTAINER...]
- 例子:
docker rm sleepy_turing # 删除指定容器 docker rm $(docker ps -aq) # 危险!删除所有已停止的容器 docker ps -aq | xargs docker rm # 同上,另一种写法
- 常用选项:
-f, --force
: 强制删除一个运行中的容器(发送SIGKILL)。-v, --volumes
: 删除容器的同时,删除与之关联的匿名卷(不会删除命名卷)。
3.5 docker logs
- 查看集装箱的航行日志
容器在后台运行时,我们需要查看它内部应用程序打印的日志。
docker logs [OPTIONS] CONTAINER
- 例子:
docker logs my_webserver # 查看日志 docker logs -f my_webserver # 实时追踪日志(像tail -f) docker logs --tail 100 my_webserver # 查看最后100行 docker logs --since 2024-01-01T00:00:00 my_webserver # 查看某个时间点之后的日志
- 常用选项:
-f, --follow
: 跟踪日志输出。--tail string
: 从日志末尾显示多少行(默认是全部)。-t, --timestamps
: 显示时间戳。--since string
: 显示某个时间戳之后的日志。--until string
: 显示某个时间戳之前的日志。
3.6 docker exec
- 进入一个正在航行的集装箱内部
有时我们需要进入一个正在运行的容器,进行一些操作,比如检查文件、调试问题、执行命令。
docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
- 例子:
# 在容器my_webserver中执行`ls /`命令 docker exec my_webserver ls /# 以交互模式(-it)进入容器内部,启动一个bash shell docker exec -it my_webserver /bin/bash # 现在你就在一个正在运行的容器内部了!可以随意操作。 # 注意:exit退出不会停止容器,只会结束当前的exec会话。
exec
vsrun
:docker run
: 创建并启动一个新容器。docker exec
: 在已运行的容器内执行额外命令。
3.7 docker cp
- 在船和集装箱之间传送货物
在主机和容器之间复制文件/文件夹。
docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH
docker cp [OPTIONS] SRC_PATH CONTAINER:DEST_PATH
- 例子:
# 从容器复制文件到主机 docker cp my_webserver:/etc/nginx/nginx.conf ./nginx.conf.bak# 从主机复制文件到容器 docker cp ./config.json my_webserver:/app/config.json
第四章:组建舰队 —— Docker Compose 多容器编排
现实中的应用很少是只有一个容器的。通常是一个“舰队”,比如一个Web应用容器 + 一个数据库容器 + 一个缓存容器。用docker run
一个个启动和管理它们太麻烦了。Docker Compose 就是用来解决这个问题的。
它允许你用一个 docker-compose.yml
文件来定义和运行多个相关联的容器。这个文件就是你的“舰队编队指令”。
4.1 安装Docker Compose
Docker Desktop for Mac/Windows 已经包含了它。在Linux上,你需要单独安装:
# 下载最新版本的Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/download/v2.23.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose# 赋予执行权限
sudo chmod +x /usr/local/bin/docker-compose# 验证安装
docker-compose --version
4.2 编写 docker-compose.yml
这是一个经典的WordPress(博客系统)示例,它包含一个wordpress
容器和一个mysql
容器。
# 版本号(注意:版本语法有变化,现代Compose建议使用 version: '3.8' 或根本不写)
version: '3.8'# 定义我们的服务(容器舰队)
services:# 第一个服务:数据库db:image: mysql:8.0volumes:- db_data:/var/lib/mysql # 使用命名卷持久化数据restart: alwaysenvironment: # 设置环境变量MYSQL_ROOT_PASSWORD: somewordpressMYSQL_DATABASE: wordpressMYSQL_USER: wordpressMYSQL_PASSWORD: wordpress# 第二个服务:WordPress网站wordpress:depends_on: # 表明它依赖于db服务,会等待db启动后再启动- dbimage: wordpress:latestports:- "8000:80" # 将主机的8000端口映射到wordpress容器的80端口restart: alwaysenvironment:WORDPRESS_DB_HOST: db:3306 # 注意这里直接用服务名`db`来访问另一个容器!WORDPRESS_DB_USER: wordpressWORDPRESS_DB_PASSWORD: wordpressWORDPRESS_DB_NAME: wordpressvolumes:- ./wp-content:/var/www/html/wp-content # 绑定挂载,用于主题/插件开发# 定义在外部声明的命名卷
volumes:db_data: {}
4.3 Compose 常用命令
在包含docker-compose.yml
文件的目录下执行以下命令:
docker-compose up
: 创建并启动所有服务。-d
: 后台运行。
docker-compose up -d
docker-compose down
: 停止并删除所有容器、网络。-v
: 同时删除匿名卷(在Compose中定义的卷不会被删除)。--rmi all
: 同时删除Compose创建的所有镜像。
docker-compose down -v
docker-compose ps
: 列出本项目下的所有容器。docker-compose logs
: 查看所有容器的日志。-f
: 跟踪日志。service_name
: 查看指定服务的日志,如docker-compose logs wordpress
。
docker-compose exec
: 进入某个服务的容器。docker-compose exec db /bin/bash # 进入db服务的容器
docker-compose restart
/docker-compose stop
/docker-compose start
: 重启、停止、启动服务。docker-compose build
: 如果服务是用build: .
定义的,这个命令可以重新构建镜像。
Compose的优势:
- 一键启停: 一个命令管理整个应用栈。
- 配置即代码:
docker-compose.yml
文件记录了整个环境配置,易于版本控制和共享。 - 服务发现: 容器之间可以使用服务名(如上面的
db
)直接通信,Compose会自动创建内部网络并配置DNS。
第五章:港口与航线 —— 网络与数据管理
5.1 网络(Network)
Docker提供了几种网络模式,让容器之间、容器与外部世界之间能够通信。
- 查看网络:
docker network ls
- 创建网络:
docker network create my-network
- 将容器连接到网络:
docker network connect my-network my-container
- 断开连接:
docker network disconnect my-network my-container
- 删除网络:
docker network rm my-network
- 网络模式:
bridge
: 默认模式。每个容器分配一个私有IP,通过网桥与主机通信。端口需要映射到主机才能被外部访问。host
: 主机模式。容器直接使用主机的网络命名空间,没有自己的IP,容器端口直接暴露在主机上。性能更好,但隔离性差。none
: 无网络。容器内没有网络栈。overlay
: ** overlay 网络**。用于Docker Swarm集群中不同主机上的容器通信。
5.2 数据卷(Volume)
数据卷是保存Docker容器生成和使用的数据的首选机制。
- 查看卷:
docker volume ls
- 创建卷:
docker volume create my-named-volume
- 检查卷的详细信息:
docker volume inspect my-named-volume # 会显示卷在主机上的实际存储位置(Mountpoint)
- 删除卷:
docker volume rm my-named-volume docker volume prune # 删除所有未被使用的卷
第六章:实战演习与故障排查
6.1 实战:部署一个简单的Python Web应用
-
项目结构:
my-app/ ├── app.py ├── requirements.txt └── Dockerfile
-
app.py
:from flask import Flask app = Flask(__name__)@app.route('/') def hello():return "Hello from Dockerized Flask App!"if __name__ == '__main__':app.run(host='0.0.0.0', port=5000)
-
requirements.txt
:Flask==2.0.1
-
Dockerfile
:FROM python:3.9-slim WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt COPY . . CMD ["python", "app.py"]
-
构建并运行:
cd my-app docker build -t my-flask-app . docker run -d -p 5000:5000 --name flask-container my-flask-app
访问
http://localhost:5000
查看结果。
6.2 常见问题排查(Debugging)
-
容器启动后立即退出:
- 原因: 通常是因为容器内前台进程执行完毕退出了。
- 排查:
docker logs flask-container # 查看日志,看有什么错误 docker run -it my-flask-app /bin/bash # 以交互模式运行,检查镜像内容
-
端口被占用:
- 错误:
Bind for 0.0.0.0:80 failed: port is already allocated
- 解决: 换一个主机端口
-p 8080:80
,或者停止正在占用端口的容器。
- 错误:
-
权限问题(尤其在Bind Mount时):
- 现象: 容器内应用无法写入挂载的目录。
- 解决: 了解Linux文件权限,或者使用命名卷(Docker会自动处理权限)。
-
docker: Error response from daemon: ...
:- 万能排查法: 仔细阅读错误信息! 99%的答案都在错误信息里。Docker的错误提示通常非常明确。
终章:远征的继续
恭喜你,船长!你已经完成了这次Docker命令的大航海,从单枪匹马的容器操作,到指挥一支Compose舰队,你已经具备了在容器化世界中航行的基本能力。
但这仅仅是开始。Docker的生态浩瀚无垠,前方还有更广阔的领域等待你去探索:
- Docker Swarm / Kubernetes: 用于在生产环境中管理和编排超大规模容器集群的“航母战斗群指挥系统”。
- CI/CD集成: 将Docker融入GitLab CI、Jenkins等持续集成/持续部署流程。
- 更安全的镜像构建: 使用多阶段构建(
multi-stage build
)减少镜像体积,避免在镜像中包含构建工具。 - 容器安全: 扫描镜像漏洞,使用非root用户运行容器。
记住,最好的学习方式就是不断实践。从今天起,尝试把你本地开发的环境用Docker容器跑起来,把你下一个项目用Dockerfile
和docker-compose.yml
描述出来。
愿你的容器之旅,一帆风顺!