"在我机器上能跑啊!"——这是开发者和运维人员之间最经典的对话之一。代码在开发环境能跑,到了测试环境就出问题;测试环境没问题,到了生产环境又崩溃。环境不一致、依赖冲突、配置繁琐,这些问题困扰着每一个开发者和运维人员。
Docker的出现,彻底改变了这一切。Docker通过容器化技术,把应用和它的所有依赖打包成一个标准化的单元(容器),可以在任何支持Docker的环境中一致运行。有了Docker,"在我机器上能跑"不再是借口,因为容器在任何机器上都能跑。
Docker在2013年由dotCloud公司发布,2014年Docker 1.0正式发布,2016年已经成为开发者和运维人员的必备技能。越来越多的公司采用Docker进行应用部署和微服务架构,Docker生态也越来越完善(Docker Compose、Docker Swarm、Kubernetes等)。
作为一个后端开发者,我从2015年开始接触Docker,2016年已经在项目中大量使用。Docker让我的开发和部署效率提升了很多,也让我对运维和架构有了更深的理解。今天就来系统地分享一下Docker容器化入门与实践,从基本概念到实战部署,帮助你快速上手Docker。
一、Docker基本概念
在开始使用Docker之前,我们需要了解一些核心概念。
1. 什么是Docker
Docker是一个开源的容器化平台,允许开发者将应用及其依赖打包成一个轻量级、可移植的容器,然后发布到任何支持Docker的机器上运行。
Docker的核心思想是:"Build, Ship, and Run Any App, Anywhere"(构建、交付、运行任何应用,在任何地方)。
Docker解决的问题:
- 环境不一致:开发、测试、生产环境统一
- 依赖冲突:每个应用有独立的依赖环境
- 快速部署:容器秒级启动,快速扩缩容
- 资源隔离:应用之间互不影响
- 易于迁移:容器可以在任何机器上运行
- 版本管理:镜像可以版本化,回滚方便
2. 镜像(Image)
镜像是Docker容器的只读模板,包含运行应用所需的一切:代码、运行时、库、环境变量、配置文件等。
镜像的特点:
- 只读:镜像一旦构建就不能修改
- 分层:镜像由多层组成,每层是一个文件系统的变更
- 可复用:基础镜像可以被多个镜像复用
- 可分享:镜像可以推送到仓库,分享给他人
常见的基础镜像:
- ubuntu/debian/centos:操作系统基础镜像
- php/python/node/java/go:语言运行时镜像
- nginx/apache/mysql/redis:服务镜像
- alpine:极简Linux镜像,体积小
3. 容器(Container)
容器是镜像的运行实例。镜像相当于"类",容器相当于"对象"。一个镜像可以创建多个容器。
容器的特点:
- 可读写:容器在镜像之上添加了一个可写层
- 隔离性:容器之间相互隔离,有独立的文件系统、网络、进程
- 轻量级:容器共享宿主机内核,启动快,资源占用少
- 可移植:容器可以在任何支持Docker的机器上运行
- 生命周期:容器可以创建、启动、停止、删除
容器 vs 虚拟机: | 对比项 | 容器 | 虚拟机 | |--------|------|--------| | 虚拟化级别 | 操作系统级 | 硬件级 | | 启动速度 | 秒级 | 分钟级 | | 资源占用 | 小(共享内核) | 大(完整操作系统) | | 性能 | 接近原生 | 有损耗 | | 隔离性 | 进程级隔离 | 完全隔离 | | 可移植性 | 高 | 中 |
4. 仓库(Registry)
仓库是存储和分发镜像的地方。
- Docker Hub:官方公共仓库,有大量官方和社区镜像
- 私有仓库:企业内部搭建的仓库,如Docker Registry、Harbor
- 国内镜像加速:由于网络原因,国内访问Docker Hub较慢,可以使用阿里云、腾讯云、DaoCloud等提供的镜像加速服务
5. Dockerfile
Dockerfile是一个文本文件,包含一系列构建镜像的指令。通过Dockerfile,可以自动化构建镜像。
常见指令:
- FROM:指定基础镜像
- MAINTAINER/LABEL:维护者信息
- RUN:执行命令
- COPY/ADD:复制文件
- WORKDIR:设置工作目录
- ENV:设置环境变量
- EXPOSE:暴露端口
- CMD/ENTRYPOINT:容器启动命令
6. Docker Compose
Docker Compose是用于定义和运行多容器Docker应用的工具。通过一个YAML文件配置应用的服务,然后用一条命令启动所有服务。
Docker Compose适合:
- 多容器应用(如Web+MySQL+Redis)
- 开发和测试环境
- 单机部署
二、Docker安装与配置
1. Linux安装(Ubuntu/Debian)
# 更新包索引
sudo apt-get update
# 安装依赖
sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common
# 添加Docker官方GPG密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
# 添加Docker仓库
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
# 更新包索引
sudo apt-get update
# 安装Docker
sudo apt-get install -y docker-ce
# 启动Docker
sudo systemctl start docker
sudo systemctl enable docker
# 验证安装
sudo docker --version
sudo docker run hello-world2. Linux安装(CentOS)
# 安装依赖
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
# 添加Docker仓库
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# 安装Docker
sudo yum install -y docker-ce
# 启动Docker
sudo systemctl start docker
sudo systemctl enable docker
# 验证安装
sudo docker --version3. Windows/Mac安装
2016年,Docker for Windows和Docker for Mac已经发布,可以直接从Docker官网下载安装包安装。
- Windows:需要Windows 10专业版或企业版,启用Hyper-V
- Mac:需要OS X 10.10.3+
也可以使用Docker Toolbox(旧版本,通过VirtualBox运行)。
4. 配置镜像加速(国内)
由于国内访问Docker Hub较慢,建议配置镜像加速。
# 创建配置目录
sudo mkdir -p /etc/docker
# 编辑配置文件
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": [
"https://registry.docker-cn.com",
"https://docker.mirrors.ustc.edu.cn"
]
}
EOF
# 重启Docker
sudo systemctl daemon-reload
sudo systemctl restart docker
# 验证
sudo docker info | grep -A 5 "Registry Mirrors"也可以使用阿里云、腾讯云等提供的专属镜像加速地址。
5. 非root用户运行Docker
# 创建docker组
sudo groupadd docker
# 将用户加入docker组
sudo usermod -aG docker $USER
# 重新登录或执行以下命令使组生效
newgrp docker
# 验证(不需要sudo)
docker run hello-world三、Docker常用命令
1. 镜像相关命令
# 搜索镜像
docker search nginx
# 拉取镜像
docker pull nginx
docker pull nginx:1.11
docker pull ubuntu:16.04
# 列出本地镜像
docker images
docker image ls
# 删除镜像
docker rmi nginx
docker image rm nginx
docker rmi -f nginx # 强制删除
# 查看镜像详情
docker inspect nginx
# 查看镜像历史
docker history nginx
# 给镜像打标签
docker tag nginx:latest my-nginx:1.0
# 推送镜像到仓库
docker push username/my-nginx:1.02. 容器相关命令
# 创建并启动容器
docker run nginx
docker run -d nginx # 后台运行
docker run -d -p 8080:80 nginx # 端口映射
docker run -d -p 8080:80 --name my-nginx nginx # 指定名称
docker run -d -p 8080:80 -v /host/path:/container/path nginx # 挂载卷
docker run -it ubuntu /bin/bash # 交互式运行
# 列出运行中的容器
docker ps
# 列出所有容器(包括停止的)
docker ps -a
# 启动/停止/重启容器
docker start my-nginx
docker stop my-nginx
docker restart my-nginx
# 进入容器
docker exec -it my-nginx /bin/bash
docker attach my-nginx # 附加到容器(不推荐)
# 查看容器日志
docker logs my-nginx
docker logs -f my-nginx # 实时查看
docker logs --tail 100 my-nginx
# 查看容器详情
docker inspect my-nginx
# 查看容器资源使用
docker stats my-nginx
# 查看容器进程
docker top my-nginx
# 复制文件到/从容器
docker cp /host/path my-nginx:/container/path
docker cp my-nginx:/container/path /host/path
# 删除容器
docker rm my-nginx
docker rm -f my-nginx # 强制删除运行中的容器
docker container prune # 删除所有停止的容器
# 暂停/恢复容器
docker pause my-nginx
docker unpause my-nginx3. 其他常用命令
# 查看Docker版本
docker --version
docker version
# 查看Docker系统信息
docker info
# 清理未使用的资源
docker system prune
docker system prune -a # 清理所有未使用的(包括镜像)
# 查看磁盘使用
docker system df四、Dockerfile编写与镜像构建
1. Dockerfile基本结构
# 基础镜像
FROM ubuntu:16.04
# 维护者
MAINTAINER Your Name <your@email.com>
# 环境变量
ENV APP_HOME /var/www/app
ENV DEBIAN_FRONTEND noninteractive
# 工作目录
WORKDIR $APP_HOME
# 安装依赖
RUN apt-get update && \
apt-get install -y nginx php-fpm php-mysql && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
# 复制文件
COPY . $APP_HOME
COPY nginx.conf /etc/nginx/nginx.conf
# 暴露端口
EXPOSE 80 443
# 数据卷
VOLUME ["/var/www/app/uploads"]
# 启动命令
CMD ["nginx", "-g", "daemon off;"]2. Dockerfile指令详解
- FROM:指定基础镜像,必须是第一条指令。尽量使用官方镜像,使用固定版本标签。
- MAINTAINER/LABEL:维护者信息,推荐使用LABEL。
- RUN:执行命令,在构建时运行。每条RUN指令会创建一个新的镜像层,建议合并多条命令减少层数。
- COPY:复制文件到镜像中。比ADD更简单,推荐使用COPY。
- ADD:复制文件,支持URL和自动解压tar包。除非需要自动解压,否则用COPY。
- WORKDIR:设置工作目录,后续的RUN、CMD、ENTRYPOINT、COPY、ADD都在这个目录下执行。
- ENV:设置环境变量,可以在构建时和运行时使用。
- ARG:构建参数,只在构建时有效,用--build-arg传递。
- EXPOSE:声明容器运行时监听的端口。只是声明,不会自动映射,需要用-p映射。
- VOLUME:声明数据卷,用于持久化数据。
- USER:设置运行容器的用户。
- CMD:容器启动时执行的命令。可以被docker run的参数覆盖。一个Dockerfile只有最后一个CMD生效。
- ENTRYPOINT:容器启动时执行的命令。不会被docker run的参数覆盖,参数会追加到ENTRYPOINT后面。
3. 构建镜像
# 构建镜像
docker build -t my-app:1.0 .
# 使用指定Dockerfile
docker build -t my-app:1.0 -f Dockerfile.prod .
# 构建时传递参数
docker build -t my-app:1.0 --build-arg ENV=production .
# 不使用缓存构建
docker build -t my-app:1.0 --no-cache .
# 查看构建历史
docker history my-app:1.04. Dockerfile最佳实践
- 使用官方基础镜像
- 使用固定版本标签,不要用latest
- 合并RUN指令,减少镜像层数
- 把变化少的指令放在前面,利用构建缓存
- 使用.dockerignore排除不需要的文件
- 不要在镜像中存储敏感信息(密码、密钥)
- 使用多阶段构建减小镜像体积(Docker 17.05+)
- 清理apt缓存和临时文件
- 使用非root用户运行容器
- 一个容器只运行一个进程
- 镜像尽量小,使用alpine基础镜像
.dockerignore示例:
.git
node_modules
vendor
*.log
.env
.DS_Store
tests
docs五、Docker Compose多容器编排
1. 安装Docker Compose
# Linux安装
sudo curl -L "https://github.com/docker/compose/releases/download/1.9.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
# 验证
docker-compose --versionWindows/Mac的Docker Desktop自带Docker Compose。
2. docker-compose.yml示例(LNMP)
version: '2'
services:
nginx:
image: nginx:1.11
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./www:/var/www/html
- ./logs/nginx:/var/log/nginx
depends_on:
- php
- mysql
restart: always
php:
build: ./php
volumes:
- ./www:/var/www/html
- ./php/php.ini:/usr/local/etc/php/php.ini
depends_on:
- mysql
- redis
restart: always
mysql:
image: mysql:5.7
ports:
- "3306:3306"
volumes:
- ./mysql/data:/var/lib/mysql
- ./mysql/conf.d:/etc/mysql/conf.d
environment:
MYSQL_ROOT_PASSWORD: root123
MYSQL_DATABASE: myapp
MYSQL_USER: myapp
MYSQL_PASSWORD: myapp123
restart: always
redis:
image: redis:3.2
ports:
- "6379:6379"
volumes:
- ./redis/data:/data
- ./redis/redis.conf:/usr/local/etc/redis/redis.conf
command: redis-server /usr/local/etc/redis/redis.conf
restart: always3. Docker Compose常用命令
# 启动所有服务
docker-compose up
docker-compose up -d # 后台运行
# 停止并删除所有服务
docker-compose down
# 启动/停止/重启服务
docker-compose start
docker-compose stop
docker-compose restart
# 查看服务状态
docker-compose ps
# 查看日志
docker-compose logs
docker-compose logs -f nginx
docker-compose logs --tail 100
# 构建服务
docker-compose build
docker-compose build php
# 进入服务容器
docker-compose exec php /bin/bash
docker-compose exec mysql mysql -u root -p
# 拉取镜像
docker-compose pull
# 查看配置
docker-compose config
# 暂停/恢复
docker-compose pause
docker-compose unpause六、实战:用Docker部署WordPress
1. 项目结构
wordpress-docker/
├── docker-compose.yml
├── nginx/
│ ├── nginx.conf
│ └── conf.d/
│ └── wordpress.conf
├── php/
│ ├── Dockerfile
│ └── php.ini
├── mysql/
│ └── conf.d/
│ └── my.cnf
└── www/
└── (WordPress文件)2. docker-compose.yml
version: '2'
services:
nginx:
image: nginx:1.11
ports:
- "80:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/conf.d:/etc/nginx/conf.d
- ./www:/var/www/html
depends_on:
- php
- mysql
restart: always
php:
build: ./php
volumes:
- ./www:/var/www/html
- ./php/php.ini:/usr/local/etc/php/php.ini
depends_on:
- mysql
restart: always
mysql:
image: mysql:5.7
volumes:
- ./mysql/data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: root123
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wp123
restart: always3. php/Dockerfile
FROM php:7.0-fpm
RUN docker-php-ext-install mysqli pdo pdo_mysql
RUN apt-get update && \
apt-get install -y libpng-dev libjpeg-dev && \
docker-php-ext-configure gd --with-jpeg-dir=/usr/include && \
docker-php-ext-install gd && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
WORKDIR /var/www/html4. nginx/conf.d/wordpress.conf
server {
listen 80;
server_name localhost;
root /var/www/html;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
fastcgi_pass php:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 30d;
}
}5. 启动
# 下载WordPress到www目录
cd www
wget https://wordpress.org/latest.tar.gz
tar -xzf latest.tar.gz
mv wordpress/* .
rm -rf wordpress latest.tar.gz
# 启动所有服务
cd ..
docker-compose up -d
# 查看状态
docker-compose ps
# 访问 http://localhost 进行WordPress安装
# 数据库主机填 mysql,用户名 wordpress,密码 wp123,数据库名 wordpress七、Docker最佳实践
1. 镜像最佳实践
- 使用官方基础镜像,安全有保障
- 使用固定版本标签,可复现构建
- 镜像尽量小,使用alpine或slim版本
- 利用构建缓存,变化少的指令放前面
- 合并RUN指令,减少层数
- 清理缓存和临时文件
- 使用多阶段构建(Docker 17.05+)
- 不要在镜像中包含敏感信息
- 定期更新基础镜像,修复安全漏洞
2. 容器最佳实践
- 一个容器只运行一个进程
- 容器是无状态的,数据持久化到数据卷
- 使用非root用户运行容器
- 限制容器的资源使用(CPU、内存)
- 设置健康检查(HEALTHCHECK)
- 容器崩溃自动重启(restart: always)
- 不要在容器中存储重要数据
- 日志输出到stdout/stderr,不要写文件
3. 安全最佳实践
- 使用官方镜像,避免未知来源的镜像
- 定期扫描镜像漏洞(Docker Security Scanning、Clair等)
- 不要以root用户运行容器
- 限制容器的系统调用(seccomp、AppArmor)
- 不要挂载敏感目录(如/var/run/docker.sock)
- 使用Docker Content Trust验证镜像签名
- 敏感信息使用环境变量或secrets,不要硬编码
- 定期更新Docker和镜像
4. 生产环境最佳实践
- 使用编排工具(Kubernetes、Docker Swarm、Mesos等)
- 服务发现和负载均衡
- 自动扩缩容
- 滚动更新和回滚
- 集中式日志收集(ELK、Fluentd等)
- 监控和告警(Prometheus、Grafana等)
- 数据备份和恢复
- 蓝绿部署或金丝雀发布
- CI/CD自动化部署
八、常见问题与解决方案
1. 容器启动后立即退出
原因:容器的主进程退出了。Docker容器运行的前提是主进程在前台运行。
解决方案:
- 检查CMD/ENTRYPOINT命令是否正确
- 确保主进程在前台运行,不要用daemon模式
- 使用docker logs查看日志
- 对于nginx,使用
CMD ["nginx", "-g", "daemon off;"] - 对于调试,可以用
docker run -it image /bin/bash进入容器手动运行命令
2. 端口映射不生效
原因:
- 容器内的服务没有监听0.0.0.0,只监听了127.0.0.1
- 端口被占用
- 防火墙阻止
解决方案:
- 确保容器内服务监听0.0.0.0
- 检查端口是否被占用:
netstat -tlnp | grep 端口 - 检查防火墙规则
- 使用
docker port container查看端口映射
3. 数据丢失
原因:容器是无状态的,删除容器后数据会丢失。
解决方案:
- 使用数据卷(VOLUME/-v)持久化数据
- 数据库的数据目录一定要挂载到宿主机
- 定期备份数据卷
- 不要用
docker rm -v删除有数据的容器
4. 镜像构建慢
原因:
- 没有利用构建缓存
- 每次都重新下载依赖
- 基础镜像拉取慢
解决方案:
- 变化少的指令放前面,利用缓存
- 依赖安装指令放前面,代码复制放后面
- 配置国内镜像加速
- 使用本地缓存的基础镜像
- 合并RUN指令,减少层数
5. 容器之间无法通信
原因:
- 容器不在同一个网络
- 使用了容器名称但不在同一个网络
- 防火墙阻止
解决方案:
- 使用Docker Compose,服务在同一个默认网络
- 使用自定义网络:
docker network create mynet,启动容器时--network mynet - 同一网络中的容器可以用容器名互相访问
- 检查防火墙规则
6. Docker磁盘占用大
原因:镜像、容器、数据卷占用大量磁盘空间。
解决方案:
# 查看磁盘使用
docker system df
# 清理停止的容器
docker container prune
# 清理未使用的镜像
docker image prune -a
# 清理未使用的数据卷
docker volume prune
# 清理所有未使用的资源
docker system prune -a --volumes总结
Docker是2013年发布的容器化技术,2016年已经成为开发者和运维人员的必备技能。Docker通过容器化技术,让应用可以在任何环境中一致运行,解决了环境不一致、依赖冲突、部署繁琐等问题。
Docker核心概念:
- 镜像(Image):容器的只读模板,包含应用和所有依赖
- 容器(Container):镜像的运行实例,轻量级、可移植、隔离
- 仓库(Registry):存储和分发镜像的地方
- Dockerfile:构建镜像的文本文件
- Docker Compose:多容器编排工具
Docker常用命令:
- 镜像:search、pull、images、rmi、build、tag、push
- 容器:run、ps、start、stop、restart、exec、logs、rm、inspect
Dockerfile最佳实践:使用官方基础镜像、固定版本标签、合并RUN指令、利用构建缓存、清理缓存、镜像尽量小。
Docker Compose适合多容器应用的开发和测试环境,通过YAML文件配置服务,一条命令启动所有服务。
生产环境建议使用编排工具(Kubernetes、Docker Swarm等),配合服务发现、负载均衡、自动扩缩容、监控告警、集中日志等。
Docker改变了软件开发和部署的方式,是每个开发者和运维人员都应该掌握的技能。希望本文能帮助你快速上手Docker,享受容器化带来的便利和效率。
最后,Docker生态在快速发展,从Docker到Kubernetes,从容器到微服务,技术在不断进步。保持学习,跟上技术的步伐,才能在这个快速变化的时代立于不败之地。
评论(0)
暂无评论,快来抢沙发~
评论功能仅对会员开放,请先登录
登录