第一次接触Docker时,我正被"这个服务在我本地能跑,为什么上线就挂?"的问题困扰。传统虚拟机的资源消耗让我团队的老旧测试服务器不堪重负,直到发现这个轻量级的容器方案。与虚拟机不同,Docker容器共享主机操作系统内核,这意味着:
去年我们有个Java服务迁移案例:原VM镜像4.2GB,容器化后仅380MB。更惊喜的是开发环境的复原能力——新成员用docker-compose up就能一键还原全套服务依赖,再也不用经历"装三天环境改两天配置"的噩梦。
镜像就像程序的安装包,但更智能。它不仅包含应用代码,还有完整的运行环境配置。我习惯用烘焙比喻:
实际操作中,你会发现镜像采用分层存储。比如构建一个Python应用镜像:
dockerfile复制FROM python:3.9-slim # 基础层(约120MB)
COPY requirements.txt . # 依赖文件层(约5KB)
RUN pip install -r requirements.txt # 依赖安装层(视依赖大小)
COPY . . # 应用代码层
每层都是只读的,这种设计让镜像共享和传输极其高效——如果两台机器都有python:3.9-slim基础层,只需要传输差异层。
启动容器就像按下蛋糕机的开始键。关键参数解析:
bash复制docker run -d --name my_web \
-p 8080:80 \
-v ./logs:/var/log/nginx \
-e "ENV=production" \
nginx:latest
-d:后台运行(detach模式)--name:给容器起个有意义的名字-p:端口映射(主机端口:容器端口)-v:目录挂载(持久化数据的关键)-e:环境变量注入警告:生产环境切勿使用
--privileged参数,这会赋予容器root权限,存在严重安全隐患
Docker Hub是默认的公共仓库,但企业更常用私有仓库:
上传下载镜像的基本操作:
bash复制# 登录仓库
docker login registry.example.com
# 打标签(格式:仓库地址/用户名/镜像名:版本)
docker tag myapp:v1 registry.example.com/devteam/myapp:v1
# 推送镜像
docker push registry.example.com/devteam/myapp:v1
# 拉取镜像
docker pull registry.example.com/devteam/myapp:v1
以Node.js项目为例,标准开发流程:
bash复制mkdir node-docker-demo && cd node-docker-demo
npm init -y
npm install express
dockerfile复制# 使用官方Node镜像
FROM node:16-alpine
# 设置工作目录
WORKDIR /usr/src/app
# 先拷贝依赖文件
COPY package*.json ./
# 安装依赖(利用Docker缓存层)
RUN npm install
# 拷贝源代码
COPY . .
# 暴露端口
EXPOSE 3000
# 启动命令
CMD ["node", "server.js"]
bash复制# 构建镜像(注意最后的点)
docker build -t node-app:v1 .
# 运行容器
docker run -p 3000:3000 -d node-app:v1
技巧:开发时添加
-v $(pwd):/usr/src/app参数实现代码热更新,避免每次修改都重建镜像
经过多个项目实践,我总结的生产级优化方案:
dockerfile复制# 构建阶段
FROM node:16 as builder
WORKDIR /app
COPY . .
RUN npm install && npm run build
# 生产阶段
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
dockerfile复制RUN groupadd -r appuser && useradd -r -g appuser appuser
USER appuser
dockerfile复制HEALTHCHECK --interval=30s --timeout=3s \
CMD curl -f http://localhost/health || exit 1
Docker构建的缓存机制是把双刃剑。我曾遇到一个构建耗时从2分钟突然变成15分钟的案例,原因是某开发者在COPY . .之前修改了package.json。正确做法:
dockerfile复制COPY package.json package-lock.json ./
RUN npm install
COPY src/ ./src
COPY public/ ./public
.dockerignore文件:code复制node_modules
.git
*.log
.DS_Store
在一次安全审计后,我们制定了强制规范:
-alpine或-slim版本bash复制# 错误做法:Dockerfile中写密码
ENV DB_PASSWORD="123456"
# 正确做法:运行时注入
docker run -e DB_PASSWORD=$(cat /secrets/db_password) ...
RUN chmod问题1:容器无法访问外网
bash复制docker exec -it container_name ping 8.8.8.8
docker network inspect bridge
bash复制# 重建docker0网桥
sudo systemctl restart docker
# 或使用自定义网络
docker network create my_network
问题2:端口冲突
bash复制# 查看占用端口
sudo netstat -tulnp | grep 8080
# 修改映射端口
docker run -p 8081:80 ...
典型误操作:
bash复制# 危险操作:删除容器连带卷
docker rm -v container_name
# 安全做法:显式管理卷
docker volume create my_volume
docker run -v my_volume:/data ...
数据备份方案:
bash复制# 创建备份容器
docker run --rm -v db_volume:/source -v $(pwd):/backup \
alpine tar czf /backup/db_backup.tar.gz -C /source .
当项目需要多个服务协同(如Web+DB+Redis),推荐使用Docker Compose。这是我最近一个微服务项目的编排文件:
yaml复制version: '3.8'
services:
web:
build: .
ports:
- "5000:5000"
environment:
- REDIS_URL=redis://redis:6379
depends_on:
- redis
- db
redis:
image: redis:6-alpine
volumes:
- redis_data:/data
db:
image: postgres:13
environment:
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
volumes:
- pg_data:/var/lib/postgresql/data
secrets:
- db_password
volumes:
redis_data:
pg_data:
secrets:
db_password:
file: ./secrets/db_password.txt
关键技巧:
depends_on控制启动顺序生产环境必须的监控手段:
bash复制# 实时状态
docker stats
# 详细监控
docker inspect container_name
# 资源限制(防止单个容器耗尽资源)
docker run --memory=512m --cpus=1.5 ...
bash复制# 查看实时日志
docker logs -f container_name
# 日志驱动配置(推荐json-file+logrotate)
docker run --log-driver=json-file \
--log-opt max-size=10m \
--log-opt max-file=3 ...
GitLab CI的Docker集成示例:
yaml复制stages:
- build
- test
- deploy
variables:
IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
build:
stage: build
script:
- docker build -t $IMAGE_TAG .
- docker push $IMAGE_TAG
test:
stage: test
image: $IMAGE_TAG
services:
- postgres:13
- redis:6
script:
- npm test
deploy:
stage: deploy
only:
- master
script:
- docker-compose -f production.yml up -d
优化技巧:
docker build --pull确保基础镜像最新docker system prune -f清理构建缓存