在Docker环境中如何运行自己的代码

 更新时间:2026年03月10日 09:44:50   作者:铉铉这波能秀  
这篇文章主要介绍了在Docker环境中如何运行自己的代码实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

一、什么是 Docker?

1.1 Docker 的定义与核心定位

Docker 是由 Docker Inc.(后被 Mirantis 收购)开发的一款开源的容器化平台,基于 Go 语言开发,遵循 Apache 2.0 开源协议。其核心定位是:将应用程序及其依赖环境打包成轻量级、可移植、自包含的容器,使得应用可以在任何支持 Docker 的环境中以相同的方式运行

通俗来讲,Docker 就像一个 “标准化的集装箱”:无论你的应用是 Python 写的 Web 服务、Node.js 开发的前端项目,还是 Java 构建的微服务,都可以被装进这个 “集装箱” 里。这个 “集装箱” 包含了应用运行所需的所有东西 —— 代码、运行时、系统工具、系统库,只要有 Docker 运行环境,这个 “集装箱” 就能无缝运行,无需担心环境差异。

1.2 Docker 的核心架构

Docker 采用客户端 - 服务器(C/S)架构,核心组件包括:

  • Docker Client(客户端):用户交互的入口,通过命令行(docker 命令)或 API 向 Docker Daemon 发送指令(如构建镜像、启动容器);
  • Docker Daemon(守护进程):运行在宿主机的后台进程,负责处理客户端的请求,管理镜像、容器、网络、数据卷等核心资源;
  • Docker Registry(镜像仓库):存储 Docker 镜像的仓库,分为公有仓库(如 Docker Hub)和私有仓库(如企业内部仓库);
  • Containerd:底层容器运行时,负责容器的创建、启动、停止等生命周期管理,Docker Daemon 不再直接操作容器,而是通过 Containerd 调用 RunC;
  • RunC:轻量级的容器运行时,遵循 OCI(开放容器倡议)标准,是容器运行的核心执行器。

核心交互流程:用户通过 Docker Client 输入 docker run 命令 → Docker Daemon 接收指令后,从 Registry 拉取镜像(若本地无)→ 调用 Containerd 创建容器 → RunC 启动容器进程,完成应用运行。

二、为什么要使用 Docker?—— 解决开发部署的核心痛点

2.1 彻底终结 “环境不一致” 的噩梦

“在我本地能跑,到测试环境就报错” 是开发人员的经典吐槽,根源在于开发、测试、生产环境的差异:

  • 开发用 macOS + Python 3.8,测试服务器是 CentOS 7 + Python 3.6,依赖包版本冲突导致代码运行异常;
  • 前端项目依赖 Node.js 16,运维部署时用了 Node.js 18,打包后的代码出现兼容性问题;
  • 数据库版本不一致:开发用 MySQL 8.0,生产用 MySQL 5.7,SQL 语法不兼容导致功能失效。

Docker 的解决方案是:将应用 + 运行环境打包成镜像,镜像在任何支持 Docker 的环境中运行结果一致。无论你是在 macOS、Windows、Linux 还是云服务器上运行,只要镜像相同,应用行为就完全一致,真正实现 “一次构建,到处运行”。

三、核心概念辨析:虚拟机、Docker 容器与镜像

要掌握 Docker,必须先理清三个核心概念:虚拟机、Docker 容器、Docker 镜像,以及它们之间的关系。

3.1 传统虚拟机:重量级的环境隔离方案

虚拟机(VM)是通过虚拟化技术在物理服务器上模拟出的独立操作系统实例,核心依赖 Hypervisor(虚拟化管理程序,如 VMware、KVM、VirtualBox)。

3.1.1 虚拟机的架构

  • 物理机(Host Machine):底层的硬件服务器,提供 CPU、内存、存储、网络等物理资源;
  • Hypervisor:运行在物理机上的虚拟化层,负责将物理资源分配给不同的虚拟机;
  • 客户机(Guest Machine):虚拟机实例,包含完整的操作系统(如 Windows、Linux)和应用程序;
  • Guest OS:虚拟机内的操作系统,每个虚拟机都有独立的内核和系统库。

3.1.2 虚拟机的特点

  • 完全隔离:每个虚拟机拥有独立的内核、文件系统、网络,与其他虚拟机和宿主机完全隔离;
  • 重量级:需要模拟完整的硬件和操作系统,启动时间长(分钟级),资源占用高(每个虚拟机需分配固定的 CPU、内存);
  • 兼容性好:可运行任何操作系统和应用,不受宿主机系统限制。

3.2 Docker 容器:轻量级的进程隔离

Docker 容器是基于 Linux 内核技术实现的轻量级隔离环境,本质上是宿主机上的一组受限制的进程

3.2.1 容器的核心隔离技术

Docker 容器的隔离性依赖 Linux 内核的两大核心特性:

  • Namespace:实现资源隔离,包括 PID(进程 ID)、NET(网络)、MNT(文件系统)、UTS(主机名)、IPC(进程间通信)、USER(用户)等 Namespace。每个容器拥有独立的 Namespace,只能看到自己的进程、网络、文件系统,无法感知宿主机或其他容器的资源;
  • Cgroup(Control Group):实现资源限制,可限制容器的 CPU、内存、磁盘 I/O、网络带宽等资源,避免容器抢占宿主机资源。

3.2.2 容器的特点

  • 轻量级:无需模拟硬件和操作系统内核,共享宿主机内核,启动时间短(毫秒级),资源占用低(按需分配资源,无需固定分配);
  • 高效隔离:进程级隔离,隔离性略弱于虚拟机,但足以满足绝大多数应用场景;
  • 可移植性:基于镜像运行,可在任何支持 Docker 的环境中迁移;
  • 快速扩缩容:容器创建 / 销毁速度快,可快速响应业务扩缩容需求。

3.3 Docker 镜像:容器的 “只读模板”

Docker 镜像(Image)是创建 Docker 容器的只读模板,包含了容器运行所需的所有文件系统、代码、运行时、依赖、配置等。

3.3.1 镜像的核心特性

  • 只读性:镜像一旦构建完成,就无法修改,只能以只读方式存在;
  • 分层结构:镜像基于 UnionFS(联合文件系统)实现分层存储,每个层都是一个只读的文件系统片段,多个镜像可共享相同的层,节省存储空间。例如:Python 3.9-alpine 镜像包含基础层(alpine 系统)、Python 运行时层、依赖层,多个基于该镜像的容器可共享这些层;
  • 可复用性:镜像可作为基础模板,构建新的镜像(如基于 Python 3.9-alpine 镜像,添加自己的代码和依赖,构建新的应用镜像)。

3.4 虚拟机 vs Docker 容器:核心差异对比

特性虚拟机Docker 容器
内核每个虚拟机有独立内核共享宿主机内核(仅 Linux 容器)
启动时间分钟级毫秒级
资源占用高(固定分配 CPU / 内存)低(按需分配,共享资源)
隔离级别硬件级(完全隔离)进程级(内核级隔离)
镜像 / 镜像体积大(包含完整操作系统,GB 级)小(仅包含应用和依赖,MB 级)
可移植性差(依赖 Hypervisor)好(跨平台运行)
扩缩容效率低(启动慢,资源固定)高(启动快,资源弹性分配)
适用场景需完全隔离的场景(如多操作系统运行)微服务、CI/CD、快速部署、环境标准化

3.5 Docker 容器与镜像的关系:模板与实例

Docker 容器和镜像的关系,类似于类与对象的关系(镜像可以理解为一个生产容器的模具):

  • 镜像:相当于 “类”,是只读的模板,定义了容器的结构和行为;
  • 容器:相当于 “对象”,是镜像的运行实例,基于镜像创建,拥有可写层(镜像为只读,容器在镜像的基础上添加一层可写层,所有修改都在可写层中进行)。

核心关系总结:

  1. 一个镜像可以创建多个容器(一个类可以实例化多个对象);
  2. 容器启动时,Docker 会加载镜像的所有只读层,并在顶部创建一个可写层;
  3. 容器停止后,可写层的数据不会丢失,重启容器后仍可访问;
  4. 删除容器时,可写层会被删除,镜像的只读层不会受影响;
  5. 可通过 docker commit 将容器的可写层转换为新的镜像层,实现镜像的更新。

示例:基于 python:3.9-alpine 镜像创建两个容器 A 和 B,A 和 B 共享镜像的只读层,各自拥有独立的可写层。修改 A 容器内的文件,只会影响 A 的可写层,不会影响 B 容器和原始镜像。

四、如何选择并拉取合适的 Docker 镜像?

镜像是 Docker 运行的基础,选择合适的镜像直接影响容器的稳定性、体积和安全性。本节将详细讲解镜像的选择原则、拉取方法和本地管理。

4.1 镜像的核心来源

4.1.1 公有镜像仓库:Docker Hub

Docker Hub(https://hub.docker.com/)是官方的公有镜像仓库,包含数百万个官方和社区镜像,是最主要的镜像来源:

  • 官方镜像:由 Docker 官方或软件厂商维护(如 pythonnodenginxmysql),安全性高、更新及时、兼容性好;
  • 社区镜像:由开发者或社区维护,可能包含定制化配置,但需注意安全性(避免恶意镜像)。

4.1.2 私有镜像仓库

企业内部通常会搭建私有镜像仓库(如 Docker Registry、Harbor),用于存储内部定制的镜像:

  • 避免敏感代码 / 配置泄露;
  • 提高镜像拉取速度(无需访问公网);
  • 统一管理企业内部的镜像版本。

4.2 选择镜像的核心原则

4.2.1 优先选择官方镜像

官方镜像经过严格测试,安全性和稳定性有保障,且有清晰的版本更新记录。

例如:选择 python:3.9-alpine 而非社区维护的 xxx/python:3.9

4.2.2 选择轻量化的镜像版本

镜像体积越小,拉取速度越快,占用存储空间越少。常见的轻量化版本:

  • alpine 版本:基于 Alpine Linux(轻量级 Linux 发行版,体积约 5MB),是最常用的轻量化版本,如 python:3.9-alpinenginx:alpine
  • slim 版本:精简版,去掉了不必要的组件,体积介于 full 版本和 alpine 版本之间,如 python:3.9-slim
  • full 版本:完整版本,包含所有组件,体积大,适合需要完整工具链的场景。

注意:alpine 版本可能缺少部分系统库,若应用依赖特定库(如 glibc),需手动安装。

4.2.3 明确指定镜像标签,避免使用 latest

latest 是镜像的默认标签,指向最新版本,但无法保证版本的稳定性(可能随时更新)。生产环境中必须指定具体版本标签,如 python:3.9.18-alpine 而非 python:latest

标签命名规则:通常包含 “主版本。次版本。补丁版本 - 系统版本”,如 node:18.18.2-alpine3.18

4.2.4 关注镜像的安全性

  • 查看镜像的漏洞扫描报告(Docker Hub 提供镜像的安全扫描功能);
  • 避免使用未知来源的社区镜像,防止包含恶意代码;
  • 定期更新镜像,修复已知漏洞。

4.2.5 考虑镜像的维护性

选择维护活跃的镜像,避免使用已停止更新的版本(如 Python 2.7 已停止维护,应避免使用)。可通过 Docker Hub 查看镜像的 “Last Updated” 时间,判断维护状态。

4.3 不同场景的镜像选择示例

应用场景推荐镜像选择理由
Python 微服务(生产)python:3.9-alpine体积小、资源占用低,适合生产环境
Python 开发环境python:3.9-slim包含基础工具链,便于调试
Node.js 前端项目部署node:18-alpine轻量化,适合打包和运行前端代码
Java Spring Boot 应用openjdk:17-jdk-alpine体积小,支持 Spring Boot 3.x
Nginx 静态资源托管nginx:alpine轻量级,性能高,适合静态资源部署
MySQL 数据库(测试)mysql:5.7-alpine轻量化,适合测试环境
MySQL 数据库(生产)mysql:8.0.36完整版本,稳定性高,支持生产环境特性

4.4 镜像拉取的核心命令与实操

4.4.1 搜索镜像

使用 docker search 命令搜索 Docker Hub 上的镜像:

bash运行:

# 搜索 Python 镜像
docker search python

# 筛选官方镜像(--filter=is-official=true)
docker search --filter=is-official=true python

# 筛选星数≥1000的镜像(--filter=stars=1000)
docker search --filter=stars=1000 python

4.4.2 拉取镜像

使用 docker pull 命令拉取镜像,格式:docker pull 镜像名:标签

bash运行:

# 拉取官方 Python 3.9-alpine 镜像
docker pull python:3.9-alpine

# 拉取指定版本的 Nginx 镜像
docker pull nginx:1.25.3-alpine

# 拉取私有仓库的镜像(需先登录)
docker pull registry.example.com/my-app:v1.0

若不指定标签,默认拉取 latest 标签:

bash运行:

docker pull python  # 等价于 docker pull python:latest

4.4.3 登录私有镜像仓库

拉取 / 推送私有镜像前,需先登录仓库:

bash运行:

# 登录 Docker Hub
docker login

# 登录私有仓库
docker login registry.example.com

输入用户名和密码后,登录信息会保存在 ~/.docker/config.json 文件中。

4.5 镜像的本地管理

4.5.1 查看本地镜像

bash运行:

# 查看所有本地镜像
docker images

# 精简输出格式(只显示镜像ID、名称、标签、大小)
docker images --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}\t{{.Size}}"

# 查看镜像的详细信息
docker inspect python:3.9-alpine

4.5.2 重命名镜像

使用 docker tag 命令为镜像添加新标签(常用于推送镜像到私有仓库):

bash运行:

# 格式:docker tag 原镜像名:标签 新镜像名:标签
docker tag python:3.9-alpine registry.example.com/my-python:3.9-alpine

4.5.3 删除镜像

使用 docker rmi 命令删除本地镜像:

bash运行:

# 删除指定镜像(通过镜像名:标签)
docker rmi python:3.9-alpine

# 删除指定镜像(通过镜像ID)
docker rmi 1234567890ab

# 强制删除(镜像被容器使用时,需加 -f)
docker rmi -f python:3.9-alpine

# 删除所有未使用的镜像(清理空间)
docker image prune -a

注意:删除镜像前,需先删除基于该镜像创建的容器(或强制删除)。

4.5.4 查看镜像构建历史

使用 docker history 命令查看镜像的分层构建历史,可排查镜像体积过大的原因:

bash运行:

docker history python:3.9-alpine

4.5.5 运行容器 / 退出容器 / 管理镜像 / 启动已停止容器

(一)运行容器

docker run:基于镜像创建 + 启动新容器,核心是「run 镜像」)

1. 基础语法

bash 运行:

docker run [可选参数] <镜像名/镜像ID> [容器内要执行的命令]
  • 镜像名 / ID:必须指定(比如 ubuntu:20.04python:3.9-slim,或镜像 ID 如 f8c79dc85f05);
  • 可选参数:控制容器的运行方式(交互式、后台、命名、端口映射等);
  • 容器内命令:可选,比如 bash(进入终端)、python app.py(运行脚本)。

2. 常用示例(从简单到复杂

场景命令示例说明
最简运行(前台)docker run ubuntu:20.04基于 ubuntu:20.04 镜像创建容器,执行镜像默认命令(通常是 bash),但无终端交互,运行后立即退出
交互式运行(常用)docker run -it ubuntu:20.04 bash-it:-i(交互式输入)+-t(分配终端),进入容器的 bash 终端,可执行命令
后台运行(守护态)docker run -d --name my-ubuntu ubuntu:20.04 sleep 3600-d:后台运行;--name:给容器命名(避免随机名称);sleep 3600:容器后台运行 1 小时
端口映射 + 后台运行docker run -d -p 8080:80 --name my-nginx nginx-p 8080:80:主机 8080 端口映射到容器 80 端口,访问主机 8080 = 访问容器 80

3. 关键参数解释

  • -it:必选(交互式操作),缺一则无法进入容器终端;
  • -d:后台运行(守护进程),容器在后台执行,不占用当前终端;
  • --name:自定义容器名(如 my-app),否则 Docker 会随机生成名称;
  • -p:端口映射(主机端口:容器端口),对外暴露容器服务;
  • -v:目录挂载(主机目录:容器目录),实现主机和容器文件共享(如 -v /host/data:/container/data)。

(二)退出容器

退出容器的核心是区分「是否停止容器」,取决于你运行容器的方式(前台 / 后台)。

1. 场景 1:交互式容器(-it 前台运行,比如 docker run -it ubuntu bash

退出方式命令 / 操作效果
停止容器并退出在容器终端输入 exit容器停止运行,回到 Linux 主机终端,容器状态变为 exited
不停止容器并退出按快捷键 Ctrl + P → Q容器继续后台运行(状态 up),仅退出容器终端,回到 Linux 主机终端

2. 场景 2:后台容器(-d 运行,比如 docker run -d my-nginx

后台容器本身不占用终端,无需 “退出”,若要操作 / 停止:

bash 运行:

# 先进入后台容器的终端(可选)
docker exec -it my-nginx bash  # 进入后可执行命令,退出用 exit(仅退出终端,容器仍运行)

# 停止后台容器(彻底“退出”容器运行)
docker stop my-nginx  # 按容器名停止;也可用容器ID:docker stop <容器ID>

(三)“启动已停止的容器”

docker run 是创建新容器(每次 run 都会生成新容器),而已停止的容器(比如 exit 后的容器)需要用 docker start 启动,这才是 “运行已有容器” 的正确方式。

1. 先查看所有容器(找到已停止的容器)

bash 运行:

docker ps -a  # -a:显示所有容器(运行中+已停止)
# 输出示例:
# CONTAINER ID   IMAGE          COMMAND       STATUS          NAMES
# abc123         ubuntu:20.04   "bash"        Exited (0) 5min ago   my-ubuntu

2. 启动已停止的容器(「运行容器」的正确方式)

bash 运行:

# 语法:docker start [可选参数] <容器名/容器ID>
docker start my-ubuntu  # 启动名为my-ubuntu的容器(后台运行)
docker start -i my-ubuntu  # -i:交互式启动(前台运行,可输入命令)

3. 重启容器(停止 + 启动)

bash 运行:

docker restart my-ubuntu  # 重启容器(无论当前是否运行)

(四)删除容器 / 镜像

1. 删除容器(需先停止,或强制删除)

bash 运行:

# 先停止容器
docker stop my-ubuntu
# 删除容器
docker rm my-ubuntu

# 强制删除运行中的容器(不推荐,除非紧急)
docker rm -f my-ubuntu

# 批量删除所有已停止容器(常用)
docker rm $(docker ps -aq --filter status=exited)

2. 删除镜像(需先删除基于该镜像的所有容器)

bash 运行:

# 先查看镜像
docker images  # 输出镜像名、标签、ID
# 示例:REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
#       ubuntu       20.04     f8c79dc85f05   2 hours ago    72.8MB

# 删除镜像(语法:docker rmi <镜像名:标签/镜像ID>)
docker rmi ubuntu:20.04  # 按名称+标签删除
docker rmi f8c79dc85f05  # 按镜像ID删除

# 强制删除被容器引用的镜像(不推荐,先删容器)
docker rmi -f ubuntu:20.04

五、实战:将自己的代码运行在 Docker 容器中

掌握了镜像的选择和拉取后,接下来进入核心实战环节:将自己的代码打包成镜像,并在容器中运行。本节将讲解通用流程,并提供多语言示例,确保你能直接落地。

5.1 前提准备:Docker 环境安装与验证

5.1.1 安装 Docker

Linux(Ubuntu/Debian)

bash运行:

# 更新软件源
sudo apt update
# 安装依赖
sudo apt install -y ca-certificates curl gnupg lsb-release
# 添加 Docker 官方 GPG 密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
# 添加 Docker 软件源
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 安装 Docker
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io
# 启动 Docker 服务
sudo systemctl start docker
# 设置开机自启
sudo systemctl enable docker
# 将当前用户加入 docker 组(避免每次使用 sudo)
sudo usermod -aG docker $USER
# 重新登录生效
logout

Windows/macOS:下载 Docker Desktop(https://www.docker.com/products/docker-desktop/),安装后打开即可,内置 Docker Engine、Docker Compose 等工具。

5.1.2 验证 Docker 安装

bash运行:

# 查看 Docker 版本
docker --version

# 运行 hello-world 容器(验证环境是否正常)
docker run hello-world

若输出 “Hello from Docker!”,说明 Docker 安装成功。

5.2 通用流程:代码容器化的核心步骤

无论使用哪种编程语言,代码容器化的核心流程都包含以下 5 步:

  1. 整理代码与依赖;
  2. 编写 Dockerfile;
  3. 构建 Docker 镜像;
  4. 启动容器运行代码;
  5. 验证与调试。

5.2.1 步骤 1:整理代码与依赖

将代码和依赖清单放在同一个目录(称为 “Docker 上下文目录”),避免冗余文件(如日志、缓存、编译产物),减少镜像体积。

依赖清单的常见形式:

  • Python:requirements.txt
  • Node.js:package.json/package-lock.json
  • Java:pom.xml(Maven)/build.gradle(Gradle);
  • Go:go.mod/go.sum

5.2.2 步骤 2:编写 Dockerfile(核心)

Dockerfile 是镜像构建脚本,定义了镜像的构建步骤。Dockerfile 是无后缀的纯文本文件(无 .txt/.sh 等后缀),默认文件名是 Dockerfile(首字母大写,行业通用规范,小写 dockerfile 也可,但不推荐);若需区分环境(如开发 / 生产),也可自定义命名(如 Dockerfile.dev/Dockerfile.prod),构建时需手动指定文件名。

不同系统创建 Dockerfile 的方法
1. Linux/macOS(终端操作)

直接通过终端命令创建空的 Dockerfile,或用编辑器编辑:

bash 运行:

# 1. 创建空的 Dockerfile(最快捷)
touch Dockerfile

# 2. 编辑 Dockerfile(选其一)
vim Dockerfile   # 用 vim 编辑(需会 vim 基本操作)
nano Dockerfile  # 用 nano 编辑(更简单,新手推荐)
code Dockerfile  # 用 VS Code 编辑(需安装 VS Code)

其他操作(自定义Dockerfile文件生成位置):

1. 确定当前所在文件夹

执行以下命令,终端会输出绝对路径(比如 /home/yourname/project),这是你当前的位置:

bash 运行:

pwd  # 打印当前工作目录(Print Working Directory)

2. 方式 1:指定目录创建 Dockerfile(推荐,先切换目录再创建)

步骤:先 cd 到目标文件夹,再创建 Dockerfile,确保文件落在预期位置。

bash 运行:

# 示例:想把Dockerfile创建在 /opt/my-docker-project 目录下
# 1. 切换到目标目录(如果目录不存在,先创建:mkdir -p /opt/my-docker-project)
cd /opt/my-docker-project

# 2. 确认已切换成功(可选)
pwd  # 输出应是 /opt/my-docker-project

# 3. 创建空的Dockerfile
touch Dockerfile

# 4. 验证文件是否存在(可选)
ls  # 会看到 Dockerfile 列在输出中

3. 方式 2:直接指定路径创建(无需切换目录)

如果不想 cd 到目标目录,可直接通过「绝对 / 相对路径」创建 Dockerfile,比如:

bash 运行:

# 绝对路径创建:直接指定 Dockerfile 的完整保存路径
touch /opt/my-docker-project/Dockerfile

# 相对路径创建:基于当前目录的子目录(比如当前在 /home/yourname,想创建到 ./docker 子目录)
mkdir -p ./docker  # 先创建子目录(如果不存在)
touch ./docker/Dockerfile

4. 验证 Dockerfile 的位置(避免建错路径)

bash 运行:

# 查看文件的绝对路径(最直观)
realpath Dockerfile  # 若在目标目录,输出如 /opt/my-docker-project/Dockerfile

# 或查看指定路径下的文件
ls /opt/my-docker-project/  # 看是否有 Dockerfile
2. Windows 系统

Windows 需注意避免自动添加 .txt 后缀,推荐 3 种方式:

方式 1:记事本手动创建

  1. 右键桌面 / 项目目录 → 新建 → 文本文档;
  2. 打开记事本,输入内容后点击「文件 → 另存为」;
  3. 「文件名」填 Dockerfile(无引号),「保存类型」选「所有文件」,「编码」选 UTF-8,点击保存;
  4. 删除自动生成的 .txt 文件(若有)。

方式 2:PowerShell/CMD 命令打开终端,进入目标目录,执行:

powershell

# Windows PowerShell
New-Item Dockerfile -ItemType File

# 或 CMD 命令
type nul > Dockerfile

方式 3:编辑器(VS Code/Notepad++)

  1. 打开 VS Code → 新建文件(Ctrl+N);
  2. 直接命名为 Dockerfile(无后缀);
  3. 保存到目标目录(Ctrl+S)。

Dockerfile内容的核心指令:

指令作用
FROM指定基础镜像(必须是第一行),如 python:3.9-alpine
WORKDIR设置容器内的工作目录(避免文件散落)
COPY把本地文件复制到容器内(格式:COPY 本地路径 容器路径)
ADD类似 COPY,支持解压压缩包、下载远程文件
RUN构建镜像时执行的命令(如安装依赖、编译代码)
ENV设置环境变量
EXPOSE声明容器暴露的端口(仅提示,不实际映射)
CMD容器启动时执行的命令(只能有一个,多写会覆盖)
ENTRYPOINT容器启动的入口命令(与 CMD 配合使用,优先级更高)
VOLUME声明数据卷(用于持久化数据)
USER指定后续命令的执行用户

Dockerfile 编写原则:

  • 尽量减少分层:将多个 RUN 命令合并为一个(用 && 连接),减少镜像层数;
  • 清理缓存:安装依赖后清理缓存文件(如 apt cleanpip cache purge),减小镜像体积;
  • 使用 .dockerignore 文件:排除不需要复制到容器的文件(如 .gitnode_modules__pycache__)。

5.2.3 步骤 3:构建 Docker 镜像

使用 docker build 命令构建镜像,格式:docker build -t 镜像名:标签 上下文路径

参数说明:

  • -t:给镜像打标签(方便识别);
  • .:上下文路径(当前目录,Docker 会读取该目录下的所有文件用于构建);
  • --no-cache:不使用缓存(强制重新构建所有层,用于调试)。

5.2.4 步骤 4:启动容器运行代码

使用 docker run 命令启动容器,核心参数:

  • -p:端口映射(宿主机端口:容器端口),如 -p 8080:5000
  • -d:后台运行容器;
  • --name:给容器命名;
  • -v:挂载数据卷(本地目录:容器目录);
  • --env:设置容器环境变量;
  • --restart:容器重启策略(如 always,容器崩溃后自动重启)。

5.2.5 步骤 5:验证与调试

  • 查看容器运行状态:docker ps
  • 访问应用:curl http://localhost:8080
  • 查看容器日志:docker logs 容器名
  • 进入容器内部调试:docker exec -it 容器名 /bin/sh
  • 查看容器详细信息:docker inspect 容器名

5.3 多语言实战示例

5.3.1 示例 1:Python Flask 应用容器化

项目结构(在Linux主机中创建)

my-python-app/
├── app.py           # 业务代码
├── requirements.txt # 依赖清单
├── Dockerfile       # 镜像构建脚本
└── .dockerignore    # 忽略文件

代码文件

app.py

python文件内容:

from flask import Flask
import os

app = Flask(__name__)

# 读取环境变量
APP_NAME = os.getenv("APP_NAME", "Docker Python App")

@app.route('/')
def hello():
    return f"Hello from {APP_NAME}! My code is running in Docker container."

if __name__ == '__main__':
    # 绑定 0.0.0.0,容器外可访问
    app.run(host='0.0.0.0', port=5000)

requirements.txt

flask==2.3.3

.dockerignore

# Git 相关
.git
.gitignore
# Python 编译/虚拟环境
__pycache__/
*.pyc
*.pyo
*.pyd
venv/
.venv/
# 敏感/本地配置
.env
.env.*
# 编辑器/系统文件
.idea/
.vscode/
.DS_Store
# 日志/临时文件
*.log
tmp/

使用

touch .dockerignore

创建,因为.开头的文件是隐藏文件,所以创建后是看不到的,可以用:

ls -a

查看文件夹中的所有文件,看到输出有.dockerignore即可。如果需要向ignore中写入内容,可以通过文本编辑器vim或nano实现:(打开nano,将要写入的内容粘贴进去,粘贴完成后,按 Ctrl+O 保存,这时底部会出现保存的文件名,再按enter键完成保存。接下来按 Ctrl+X 退出 nano。)

nano .dockerignore

Dockerfile

FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt && pip cache purge
COPY . .
ENV APP_NAME="My Python Docker App"
EXPOSE 5000
CMD ["python", "app.py"]

使用:touch Dockerfile构建

【注:虽然后面没有手动执行 docker pull 命令,但镜像拉取的动作在 docker build 阶段被自动触发了—— 核心是 Dockerfile 里的 FROM 指令,Docker 会在构建时自动完成 “检查本地镜像→缺失则拉取” 的流程。「等价于 docker pull python:3.9-slim」的操作】

构建与运行

bash运行:

# 构建镜像
docker build -t my-python-app:v1 .

# 启动容器(端口映射 8080:5000,后台运行)
docker run -p 8080:5000 -d --name my-python-container my-python-app:v1

# 验证
curl http://localhost:8080
# 输出:Hello from My Python Docker App! My code is running in Docker container.

# 查看日志
docker logs my-python-container

如果构建过程中卡住了,可以通过Ctrl+C结束进程,通过:

docker builder prune -f

清理 Docker 构建缓存。如果之前构建过 my-python-app:v1 镜像,想删除后重新构建,执行:

# 删除指定镜像
docker rmi my-python-app:v1
# 若镜像被容器引用,先删除容器再删镜像:
docker rm -f flask-app && docker rmi my-python-app:v1

之后再运行构建代码,构建完成:

运行容器:

docker run -d -p 5000:5000 --name flask-app my-python-app:v1

在浏览器顶部访问:http://localhost:5000,即可查看到运行结果

如果使用后想停止运行容器,可以使用docker ps查看容器列表

# 仅显示运行中的容器
docker ps  
# 或查看所有容器(包括已停止的)
docker ps -a

输出示例(关键看 NAMES 列是 flask-appPORTS 列是 0.0.0.0:5000->5000/tcp):

 临时停止容器(保留容器,可重启)

如果只是想停止运行,但后续还想重启(比如修改代码后重新启动),bash 运行:

# 方式1:用容器名称停止(推荐,直观)
docker stop flask-app

# 方式2:用容器ID停止(替换为你的容器ID,比如 abc123456789)
docker stop abc123456789

停止后,再次执行 docker ps 会看不到该容器,docker ps -a 能看到状态变为 Exited (0)

重启已停止的容器(临时停止后想恢复运行)

bash 运行:

# 用名称重启
docker start flask-app

# 用ID重启
docker start abc123456789

4. 彻底停止并删除容器(无需保留)

如果确认后续不需要该容器,可直接停止并删除,bash 运行:

# 方式1:先停止再删除(稳妥)
docker stop flask-app && docker rm flask-app

# 方式2:强制删除运行中的容器(无需先停止,快捷)
docker rm -f flask-app

清理关联资源(可选)

删除镜像(如果后续不需要该镜像)连构建的 my-python-app:v1 镜像也删除。bash 运行:

# 先确保容器已删除,再删镜像
docker rmi my-python-app:v1

# 若镜像被其他容器引用,强制删除
docker rmi -f my-python-app:v1

5.4 进阶优化:让容器运行更实用

5.4.1 数据卷(Volume):持久化数据

容器内的数据默认存储在可写层中,容器删除后数据会丢失。数据卷用于将容器内的目录挂载到宿主机或命名卷,实现数据持久化。

绑定挂载(本地目录 → 容器目录)

bash运行:

# 将本地 ./data 目录挂载到容器 /app/data 目录
docker run -p 8080:5000 -v $(pwd)/data:/app/data my-python-app:v1

命名卷(Docker 管理的卷)

bash运行:

# 创建命名卷
docker volume create my-data

# 挂载命名卷到容器
docker run -p 8080:5000 -v my-data:/app/data my-python-app:v1

# 查看卷信息
docker volume inspect my-data
5.4.2 Docker Compose:多容器管理

当应用依赖多个服务(如 MySQL、Redis)时,使用 Docker Compose 可一键启动所有服务。

示例 docker-compose.yml

yaml

version: '3.8'

services:
  # 应用服务
  app:
    build: .
    ports:
      - "8080:5000"
    environment:
      - APP_NAME=My Python Docker App
      - REDIS_HOST=redis
      - MYSQL_HOST=mysql
      - MYSQL_USER=root
      - MYSQL_PASSWORD=123456
      - MYSQL_DB=test
    volumes:
      - ./data:/app/data
    depends_on:
      - redis
      - mysql
    restart: always

  # Redis 服务
  redis:
    image: redis:alpine
    ports:
      - "6379:6379"
    volumes:
      - redis-data:/data
    restart: always

  # MySQL 服务
  mysql:
    image: mysql:5.7
    ports:
      - "3306:3306"
    environment:
      - MYSQL_ROOT_PASSWORD=123456
      - MYSQL_DATABASE=test
    volumes:
      - mysql-data:/var/lib/mysql
    restart: always

# 命名卷
volumes:
  redis-data:
  mysql-data:

启动 / 停止服务

bash运行:

# 启动所有服务(后台运行)
docker-compose up -d

# 查看服务状态
docker-compose ps

# 查看日志
docker-compose logs app

# 停止服务
docker-compose down

# 停止服务并删除数据卷
docker-compose down -v

5.4.3 热重载(开发环境)

开发环境中,修改代码后希望容器自动重启,无需重新构建镜像。

Python 示例(使用 flask-reload

修改 Dockerfile 的启动命令:

CMD ["python", "-m", "flask", "run", "--host=0.0.0.0", "--port=5000", "--reload"]

启动容器时挂载代码目录:

bash运行:

docker run -p 8080:5000 -v $(pwd):/app my-python-app:v1

修改本地 app.py 后,Flask 会自动重启,无需重启容器。

5.5 调试与排错:容器运行常见问题解决

5.5.1 容器启动后访问不通

  • 检查端口映射:确认 docker run 命令使用了 -p 参数,且宿主机端口未被占用;
  • 检查代码绑定地址:确保服务绑定 0.0.0.0,而非 127.0.0.1(容器内 127.0.0.1 仅容器自身可访问);
  • 检查防火墙:宿主机防火墙是否放行映射的端口;
  • 查看容器日志:docker logs 容器名,排查代码报错。

5.5.2 依赖安装失败

  • 检查网络:容器是否能访问外网(可进入容器 ping baidu.com 测试);
  • 使用国内源:在 Dockerfile 中配置国内源(如 pip、npm、maven 国内源);
  • 检查依赖版本:依赖版本与基础镜像不兼容(如 Python 3.9 安装不支持的包版本)。

5.5.3 镜像体积过大

  • 使用多阶段构建:仅保留运行所需文件;
  • 清理缓存:安装依赖后清理缓存(如 apt cleanpip cache purge);
  • 合并 RUN 命令:减少镜像层数;
  • 使用轻量化基础镜像(如 alpine 版本)。

5.5.4 容器崩溃自动重启

  • 设置重启策略:docker run --restart=always
  • 查看崩溃原因:docker logs 容器名,排查代码或依赖问题;
  • 限制容器资源:docker run --memory=512m --cpus=1,避免资源耗尽。

六、总结

Docker 作为容器化技术的标杆,已成为现代软件开发和运维的必备工具。其核心价值在于解决了环境一致性、资源隔离、快速部署等核心痛点,为微服务架构、CI/CD 流水线、云原生应用提供了坚实的基础。本文从 Docker 的定义、使用价值、核心概念、镜像选择、代码容器化实战等维度,全面讲解了 Docker 的核心知识。

总结核心要点:

  1. Docker 是轻量级的容器化平台,核心是 “一次构建,到处运行”;
  2. Docker 容器是宿主机上的受限制进程,基于镜像运行,镜像为只读模板;
  3. 选择镜像时应优先官方、轻量化、指定版本的镜像;
  4. 代码容器化的核心是编写 Dockerfile,通过 docker build 构建镜像,docker run 启动容器;
  5. 结合 Docker Compose 可轻松管理多服务依赖,提升部署效率。

未来,Docker 将继续与 Kubernetes(k8s) 深度融合,成为云原生技术的核心组件。掌握 Docker 不仅能提升开发 / 部署效率,更是进入云原生领域的必备技能。

附录:Docker 常用命令速查表

镜像管理

命令作用
docker search <name>搜索镜像
docker pull <name>:<tag>拉取镜像
docker images查看本地镜像
docker rmi <name>:<tag>删除镜像
docker tag <old> <new>重命名镜像
docker history <name>查看镜像构建历史
docker image prune -a删除未使用的镜像

容器管理

命令作用
docker run <options> <image>启动容器
docker ps查看运行中的容器
docker ps -a查看所有容器
docker stop <name/id>停止容器
docker start <name/id>启动已停止的容器
docker restart <name/id>重启容器
docker rm <name/id>删除容器
docker exec -it <name/id> sh进入容器内部
docker logs <name/id>查看容器日志
docker inspect <name/id>查看容器 / 镜像详细信息
docker container prune删除已停止的容器

Docker Compose

命令作用
docker-compose up启动服务
docker-compose up -d后台启动服务
docker-compose down停止并删除服务
docker-compose ps查看服务状态
docker-compose logs <service>查看服务日志
docker-compose build构建服务镜像
docker-compose restart <service>重启服务

最后

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 替换docker容器中的一个文件的实现

    替换docker容器中的一个文件的实现

    在某些情况下,我们可能确实需要更新容器内的文件,本文主要介绍了替换docker容器中的一个文件的实现,具有一定的参考价值,感兴趣的可以了解一下
    2024-06-06
  • 在 Docker 中查看日志的方法

    在 Docker 中查看日志的方法

    文章介绍了如何在Docker中查看容器的日志,包括使用dockerlogs命令的基本方法、实时查看日志、查看特定时间范围内的日志以及配置日志驱动程序,还提到了通过docker-compose查看多个服务的日志,并讨论了日志轮换和集成日志聚合工具的高级技巧,感兴趣的朋友一起看看吧
    2025-03-03
  • 关于immich docker-compose.yml配置文件详解

    关于immich docker-compose.yml配置文件详解

    Immich是一个自托管的照片和视频备份解决方案,允许用户在私有服务器上存储、管理和分享他们的媒体文件,项目提供了自托管、照片和视频备份、易于访问、数据控制、隐私保护等功能,通过Docker容器化部署,用户可以方便地安装和维护Immich应用
    2025-03-03
  • 详解Docker容器的日志处理

    详解Docker容器的日志处理

    这篇文章主要介绍了详解Docker容器的日志处理,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-01-01
  • docker没有错误日志,镜像服务却启动不成功的问题以及排查方式

    docker没有错误日志,镜像服务却启动不成功的问题以及排查方式

    这篇文章主要介绍了docker没有错误日志,镜像服务却启动不成功的问题以及排查方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-05-05
  • 浅谈docker避免每次sudo方法

    浅谈docker避免每次sudo方法

    本文主要介绍了docker避免每次sudo方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-11-11
  • 从入门到精通Docker Compose 轻松部署微服务实战教程

    从入门到精通Docker Compose 轻松部署微服务实战教程

    本文介绍使用Docker Compose部署基于SpringCloudAlibaba的微服务项目,涵盖用户登录积分功能,涉及Gateway、Redis、MySQL等组件,通过编写Dockerfile和YAML配置文件,结合脚本实现环境容器与服务容器的自动化部署与验证,感兴趣的朋友一起看看吧
    2025-07-07
  • docker 挂载MySQL实现数据持久化的实现

    docker 挂载MySQL实现数据持久化的实现

    本文主要介绍了docker 挂载MySQL实现数据持久化的实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • Docker容器迁移Oracle到MySQL的实现方法

    Docker容器迁移Oracle到MySQL的实现方法

    本文主要介绍了Docker容器迁移Oracle到MySQL的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • 解决docker数据文件过大导致根磁盘满的问题

    解决docker数据文件过大导致根磁盘满的问题

    本篇文章主要介绍了解决docker数据文件过大导致根磁盘满的问题,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-04-04

最新评论