前言
在现代软件开发流程中,环境不一致一直是开发团队的痛点。“本地运行好好的,一到服务器就报错”,这类问题相信很多开发者都遇到过。传统虚拟机方案资源开销大、启动慢,而Docker容器技术凭借轻量、隔离、可移植的优势,已经成为后端开发、运维人员必备技能。本文将从Docker基础概念入手,讲解核心命令、镜像构建、容器运行,再到完整项目实战,帮助读者从零掌握Docker的日常开发使用。
一、Docker核心概念理解
Docker的本质是操作系统级虚拟化,它没有完整虚拟机的硬件模拟,直接复用宿主机内核,只隔离应用程序运行环境。我们需要先分清三个核心概念:镜像(Image)、容器(Container)、Dockerfile。
- 镜像Image:可以理解为软件的“模板”,是只读的文件包,包含程序代码、运行依赖、配置文件、运行环境。镜像不能直接运行,它是创建容器的原材料。比如官方的
nginx镜像,就内置了Nginx服务全部运行所需文件。 - 容器Container:镜像运行起来之后的实例,是镜像的可读写运行状态。同一个镜像,可以启动无数个独立容器,容器之间相互隔离。容器可以被启动、停止、删除,容器删除后,内部写入的数据默认会丢失。
- Dockerfile:用来构建镜像的文本脚本文件,我们可以编写Dockerfile,自定义我们自己项目的镜像,实现项目环境的标准化打包。
通俗比喻:镜像相当于类,容器相当于类实例;Dockerfile就是用来生成类的源代码。
二、Docker常用基础命令实操
2.1 镜像相关命令
# 从DockerHub拉取官方镜像
docker pull nginx:1.25
# 查看本地所有镜像
docker images
# 删除本地镜像
docker rmi nginx:1.25
2.2 容器管理命令
# 基于镜像启动容器,-d后台运行,-p端口映射 宿主机端口:容器内部端口
docker run -d -p 8080:80 --name mynginx nginx:1.25
# 查看正在运行的容器
docker ps
# 查看全部容器(包含停止的)
docker ps -a
# 停止容器
docker stop mynginx
# 启动已经停止的容器
docker start mynginx
# 删除容器
docker rm mynginx
端口映射是非常关键的知识点:容器内部的服务默认只能容器内部访问,必须通过
-p参数把容器端口映射到宿主机,外部网络才可以访问服务。
三、实战:使用Dockerfile打包Python项目
我们拿一个简单Python Flask项目做案例,演示如何自定义构建镜像。
项目目录结构
demo_app/
├── app.py
├── requirements.txt
└── Dockerfile
app.py代码:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return "Hello Docker!这是我的第一个容器化项目"
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
requirements.txt
flask==2.3.3
编写Dockerfile文件:
# 基础镜像:使用官方python3.11镜像
FROM python:3.11-slim
# 设置工作目录
WORKDIR /app
# 复制依赖文件
COPY requirements.txt .
# 安装依赖包
RUN pip install -r requirements.txt
# 复制项目全部代码
COPY . .
# 暴露容器端口
EXPOSE 5000
# 容器启动执行命令
CMD ["python","app.py"]
构建镜像并运行容器
# 构建镜像,-t指定镜像名称:标签
docker build -t flask-demo:v1 .
# 运行容器,映射5000端口
docker run -d -p 5000:5000 --name flask-app flask-demo:v1
执行完成后,浏览器访问 http://localhost:5000,就可以看到页面输出。至此,我们完成了把Python应用打包成容器镜像。无论在哪台机器,只要安装Docker,就可以直接运行这个镜像,不会出现环境版本不一致问题。
四、开发中Docker的常见踩坑总结
- 容器内程序必须监听0.0.0.0 很多新手写程序默认监听
127.0.0.1,此时容器外部无法访问,必须修改监听地址为0.0.0.0。 - 数据持久化问题 容器删除,容器内数据全部丢失。如果需要保存数据库、日志文件,要使用
-v挂载宿主机目录到容器。
# 挂载宿主机目录到容器
docker run -v /host/path:/container/path 镜像名
- 镜像体积优化
python:slim轻量镜像比完整python镜像体积小很多;Dockerfile中尽量合并RUN指令,减少镜像层数。 - 不要在容器内修改代码 容器是运行实例,开发调试建议本地写代码,挂载目录同步到容器,不要直接在容器内部改代码。
五、Docker在团队开发中的价值
- 统一开发环境:开发、测试、生产环境使用完全一致镜像,消除环境差异。
- 快速部署:打包好镜像之后,服务器只需要拉取镜像启动容器即可,不需要手动安装一堆依赖。
- 资源隔离:不同项目运行在独立容器,互不干扰。
- 便于CI/CD流水线集成:现在绝大多数自动化部署流程,都是基于Docker镜像完成。
总结
Docker容器技术不是一个复杂高深的黑科技,它的核心思想就是“一次构建,到处运行”。本文从基础概念,到命令实操,再到完整Python项目的容器化打包,覆盖了日常开发高频使用场景。
想要深入学习Docker,可以继续学习Docker Compose多容器编排、Docker Swarm、K8s容器编排。在实际工作中,建议多动手练习,自己写Dockerfile、调试容器,在实践中理解容器的工作原理。