Docker是一种容器化技术,可以把应用和它的依赖打包到一个轻量级、可移植的容器中。使用Docker,你再也不用担心"在我电脑上能跑"的问题,环境一致性得到了完美保证。
一、Docker核心概念
- 镜像(Image):应用的只读模板,包含运行应用所需的一切(代码、运行时、库、环境变量)
- 容器(Container):镜像的运行实例,可以理解为"运行中的虚拟机"(但更轻量)
- 仓库(Registry):存储镜像的地方,Docker Hub是最大的公共仓库
- Dockerfile:构建镜像的脚本文件,定义镜像的内容
二、安装Docker
# Ubuntu/Debian 安装
sudo apt update
sudo apt install docker.io docker-compose -y
# CentOS/RHEL 安装
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install docker-ce docker-ce-cli containerd.io docker-compose -y
# 启动并设置开机自启
sudo systemctl start docker
sudo systemctl enable docker
# 验证安装
docker --version
docker-compose --version
三、常用命令
# 镜像操作
docker pull nginx:latest # 拉取镜像
docker images # 查看本地镜像
docker rmi nginx:latest # 删除镜像
docker image prune # 清理无用镜像
# 容器操作
docker run -d --name web -p 80:80 nginx # 启动容器
docker ps # 查看运行中的容器
docker ps -a # 查看所有容器(含已停止)
docker stop web # 停止容器
docker start web # 启动已停止的容器
docker restart web # 重启容器
docker rm web # 删除容器
docker logs web # 查看日志
docker exec -it web /bin/bash # 进入容器内部
四、编写Dockerfile
Node.js项目示例
# Dockerfile
FROM node:18-alpine
# 设置工作目录
WORKDIR /app
# 复制依赖文件(利用Docker缓存层)
COPY package*.json ./
# 安装依赖
RUN npm install --production
# 复制源代码
COPY . .
# 暴露端口
EXPOSE 3000
# 启动命令
CMD ["node", "server.js"]
Python项目示例
# Dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "app:app"]
PHP项目示例
# Dockerfile
FROM php:8.2-apache
# 安装扩展
RUN docker-php-ext-install pdo pdo_mysql mysqli
# 启用Apache模块
RUN a2enmod rewrite
# 复制项目文件
COPY . /var/www/html/
# 设置权限
RUN chown -R www-data:www-data /var/www/html
EXPOSE 80
五、Docker Compose编排
当项目需要多个服务(Web + 数据库 + 缓存等)时,使用docker-compose统一管理。
# docker-compose.yml
version: '3.8'
services:
# Web应用
web:
build: .
ports:
- "8080:80"
volumes:
- .:/var/www/html
depends_on:
- mysql
- redis
environment:
- DB_HOST=mysql
- DB_NAME=myapp
- REDIS_HOST=redis
restart: always
# MySQL数据库
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root_password
MYSQL_DATABASE: myapp
MYSQL_USER: app_user
MYSQL_PASSWORD: app_password
volumes:
- mysql_data:/var/lib/mysql
- ./sql/init.sql:/docker-entrypoint-initdb.d/init.sql
ports:
- "3306:3306"
restart: always
# Redis缓存
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis_data:/data
restart: always
# Nginx反向代理
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf
- ./ssl:/etc/nginx/ssl
depends_on:
- web
restart: always
volumes:
mysql_data:
redis_data:
小贴士:使用 docker-compose up -d 可以一键启动所有服务,docker-compose down 停止所有服务。非常适合团队协作和CI/CD流程。
六、常用运维命令
# Docker Compose 操作
docker-compose up -d # 后台启动所有服务
docker-compose down # 停止并删除
docker-compose restart web # 重启指定服务
docker-compose logs -f web # 实时查看日志
docker-compose ps # 查看服务状态
docker-compose exec mysql bash # 进入MySQL容器
# 数据库备份
docker-compose exec mysql mysqldump -u root -proot_password myapp > backup.sql
# 数据库恢复
docker-compose exec -T mysql mysql -u root -proot_password myapp < backup.sql
七、最佳实践
- 使用 .dockerignore 文件:排除 node_modules、.git 等不需要的文件
- 多阶段构建:减小最终镜像体积
- 不要以root用户运行:使用 USER 指令切换到非root用户
- 使用健康检查:HEALTHCHECK 确保服务正常运行
- 数据持久化:使用 volumes 保存数据库等持久数据
八、镜像优化技巧
# 多阶段构建示例(Node.js)
# 第一阶段:构建
FROM node:18 AS builder
WORKDIR /app
COPY . .
RUN npm install && npm run build
# 第二阶段:生产(只包含构建结果)
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
EXPOSE 80
优化要点:
- 用
alpine 基础镜像,体积比 debian 小很多
- 多阶段构建,最终镜像不包含构建工具和源码
- 合并 RUN 命令,减少镜像层数
- 使用
.dockerignore 排除 node_modules、.git 等
九、CI/CD 自动化部署
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build Docker Image
run: docker build -t myapp:latest .
- name: Deploy to Server
run: |
ssh user@server 'docker pull myapp:latest'
ssh user@server 'docker-compose up -d'
十、常见问题排查
- 容器启动后立即退出:用
docker logs 容器名 查看错误日志,通常是配置或依赖问题
- 端口冲突:宿主机端口被占用,用
ss -tlnp 检查,或换个映射端口
- 磁盘空间不足:定期清理无用镜像
docker system prune -a
- 数据丢失:一定要用 volumes 持久化数据库数据,不要存在容器内
总结:Docker 让部署变得可重复、可控制。新手建议从简单的单容器开始,熟悉后再用 docker-compose 编排多服务。