Docker是目前最流行的容器化技术,它彻底改变了软件的开发、分发和部署方式。通过Docker,我们可以将应用及其依赖打包成一个轻量级、可移植的容器,然后在任何支持Docker的环境中运行,实现"一次构建,到处运行"。掌握Docker,已经成为现代开发者的必备技能。今天就来分享Docker的入门教程和容器化部署实战。

Docker简介

Docker是一个开源的应用容器引擎,基于Go语言开发,2013年由dotCloud公司(后改名为Docker Inc.)发布。Docker可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化。

Docker的核心概念

  • 镜像(Image):Docker镜像是一个只读的模板,包含运行应用所需的代码、运行时、库、环境变量和配置文件。镜像可以用来创建Docker容器。
  • 容器(Container):Docker容器是镜像运行时的实例,是一个轻量级、可执行的独立软件包,包含运行应用所需的一切。容器之间相互隔离,互不影响。
  • 仓库(Repository):Docker仓库是存放镜像的地方,分为公共仓库和私有仓库。Docker Hub是最大的公共仓库,存放了大量的官方和社区镜像。

Docker的优势

  1. 快速部署:容器启动只需要几秒钟,大大缩短了部署时间。
  2. 环境一致性:开发、测试、生产环境使用相同的镜像,避免了"在我机器上能运行"的问题。
  3. 轻量级:容器共享宿主机的内核,比虚拟机更轻量,资源消耗更少。
  4. 可移植性:一次构建,到处运行,可以在任何支持Docker的环境中运行。
  5. 隔离性:容器之间相互隔离,应用之间互不影响,提高了系统的安全性和稳定性。
  6. 可扩展性:可以快速创建和销毁容器,轻松实现水平扩展。
  7. 版本管理:镜像支持版本管理,可以轻松回滚到之前的版本。

Docker vs 虚拟机: | 特性 | Docker容器 | 虚拟机 | |------|-----------|--------| | 启动速度 | 秒级 | 分钟级 | | 资源消耗 | 低(共享内核) | 高(完整操作系统) | | 隔离性 | 进程级隔离 | 系统级隔离 | | 镜像大小 | MB级 | GB级 | | 性能 | 接近原生 | 有一定损耗 |

Docker安装

Ubuntu/Debian安装

# 更新软件源
sudo apt-get update

# 安装依赖
sudo apt-get install 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"

# 更新软件源并安装Docker
sudo apt-get update
sudo apt-get install docker-ce

# 启动Docker并设置开机自启
sudo systemctl start docker
sudo systemctl enable docker

# 验证安装
sudo docker --version
sudo docker run hello-world

CentOS/RHEL安装

# 安装依赖
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 docker-ce

# 启动Docker并设置开机自启
sudo systemctl start docker
sudo systemctl enable docker

# 验证安装
sudo docker --version

将当前用户加入docker组(避免每次都用sudo)

sudo usermod -aG docker $USER
# 重新登录或执行以下命令使组生效
newgrp docker

Docker基本命令

1. 镜像管理

# 搜索镜像
docker search nginx

# 拉取镜像(默认最新版本)
docker pull nginx

# 拉取指定版本的镜像
docker pull nginx:1.21

# 查看本地镜像
docker images

# 删除镜像
docker rmi nginx:1.21

# 构建镜像(在Dockerfile所在目录执行)
docker build -t myapp:1.0 .

# 给镜像打标签
docker tag myapp:1.0 myapp:latest

# 推送镜像到仓库
docker push myapp:1.0

2. 容器管理

# 运行容器
docker run nginx

# 后台运行容器
docker run -d nginx

# 指定容器名称
docker run -d --name mynginx nginx

# 端口映射(宿主机端口:容器端口)
docker run -d -p 8080:80 nginx

# 挂载数据卷(宿主机路径:容器路径)
docker run -d -v /data/nginx:/usr/share/nginx/html nginx

# 进入容器
docker exec -it mynginx /bin/bash

# 查看运行中的容器
docker ps

# 查看所有容器(包括已停止的)
docker ps -a

# 停止容器
docker stop mynginx

# 启动已停止的容器
docker start mynginx

# 重启容器
docker restart mynginx

# 删除容器(容器必须先停止)
docker rm mynginx

# 强制删除运行中的容器
docker rm -f mynginx

# 查看容器日志
docker logs mynginx

# 实时查看容器日志
docker logs -f mynginx

# 查看容器详情
docker inspect mynginx

# 查看容器资源使用情况
docker stats mynginx

3. 数据卷管理

# 创建数据卷
docker volume create myvolume

# 查看数据卷
docker volume ls

# 查看数据卷详情
docker volume inspect myvolume

# 使用数据卷
docker run -d -v myvolume:/data nginx

# 删除数据卷
docker volume rm myvolume

# 删除未使用的数据卷
docker volume prune

4. 网络管理

# 查看网络
docker network ls

# 创建网络
docker network create mynetwork

# 查看网络详情
docker inspect mynetwork

# 容器加入网络
docker run -d --network mynetwork --name mynginx nginx

# 删除网络
docker network rm mynetwork

# 删除未使用的网络
docker network prune

Dockerfile详解

Dockerfile是用来构建Docker镜像的文本文件,包含了一系列构建镜像的指令。

常用指令

  • FROM:指定基础镜像,必须是第一条指令
  • MAINTAINER:指定维护者信息(已过时,推荐用LABEL)
  • LABEL:添加元数据,如作者、版本、描述等
  • RUN:执行命令,用于安装软件、配置环境等
  • CMD:容器启动时执行的命令,只能有一个CMD,多个时只有最后一个生效
  • ENTRYPOINT:容器启动时执行的命令,和CMD类似,但是不会被docker run的参数覆盖
  • WORKDIR:设置工作目录,后续的RUN、CMD、ENTRYPOINT、COPY、ADD都在这个目录下执行
  • ENV:设置环境变量
  • ARG:设置构建参数,只在构建时有效
  • COPY:复制文件到镜像中
  • ADD:复制文件到镜像中,支持自动解压tar包和从URL下载
  • EXPOSE:声明容器暴露的端口
  • VOLUME:声明数据卷
  • USER:设置运行容器的用户
  • HEALTHCHECK:健康检查

Dockerfile示例(PHP应用)

# 基础镜像
FROM php:7.4-fpm

# 维护者信息
LABEL maintainer="yourname@example.com"
LABEL version="1.0"
LABEL description="PHP application"

# 设置工作目录
WORKDIR /var/www/html

# 安装依赖
RUN apt-get update && apt-get install -y \
    git \
    unzip \
    libpng-dev \
    libjpeg-dev \
    libfreetype6-dev \
    && docker-php-ext-configure gd --with-freetype --with-jpeg \
    && docker-php-ext-install gd pdo pdo_mysql mysqli \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

# 安装Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

# 复制应用代码
COPY . .

# 安装PHP依赖
RUN composer install --no-dev --optimize-autoloader

# 设置权限
RUN chown -R www-data:www-data /var/www/html \
    && chmod -R 755 /var/www/html

# 暴露端口
EXPOSE 9000

# 启动命令
CMD ["php-fpm"]

构建镜像

# 构建镜像(-t指定镜像名和标签,.表示Dockerfile在当前目录)
docker build -t myphpapp:1.0 .

# 查看构建的镜像
docker images

# 运行容器
docker run -d -p 9000:9000 --name myphpapp myphpapp:1.0

Docker Compose

Docker Compose是用于定义和运行多容器Docker应用的工具。通过Compose,我们可以使用YAML文件来配置应用的服务,然后用一个命令创建并启动所有服务。

安装Docker Compose

# 下载Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/download/v2.20.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# 添加执行权限
sudo chmod +x /usr/local/bin/docker-compose

# 验证安装
docker-compose --version

docker-compose.yml示例(LNMP环境)

version: '3.8'

services:
  # Nginx服务
  nginx:
    image: nginx:1.21
    container_name: lnmp-nginx
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/conf:/etc/nginx/conf.d
      - ./nginx/logs:/var/log/nginx
      - ./www:/var/www/html
    depends_on:
      - php
      - mysql
    networks:
      - lnmp-network
    restart: always

  # PHP服务
  php:
    build: ./php
    container_name: lnmp-php
    volumes:
      - ./www:/var/www/html
      - ./php/php.ini:/usr/local/etc/php/php.ini
    depends_on:
      - mysql
      - redis
    networks:
      - lnmp-network
    restart: always

  # MySQL服务
  mysql:
    image: mysql:5.7
    container_name: lnmp-mysql
    ports:
      - "3306:3306"
    volumes:
      - ./mysql/data:/var/lib/mysql
      - ./mysql/conf:/etc/mysql/conf.d
    environment:
      MYSQL_ROOT_PASSWORD: root123456
      MYSQL_DATABASE: app_db
      MYSQL_USER: app_user
      MYSQL_PASSWORD: app123456
    networks:
      - lnmp-network
    restart: always

  # Redis服务
  redis:
    image: redis:6.2
    container_name: lnmp-redis
    ports:
      - "6379:6379"
    volumes:
      - ./redis/data:/data
      - ./redis/redis.conf:/etc/redis/redis.conf
    command: redis-server /etc/redis/redis.conf
    networks:
      - lnmp-network
    restart: always

# 网络
networks:
  lnmp-network:
    driver: bridge

Docker Compose常用命令

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

# 启动指定服务
docker-compose up -d nginx

# 停止所有服务
docker-compose stop

# 停止指定服务
docker-compose stop nginx

# 停止并删除容器、网络
docker-compose down

# 查看服务状态
docker-compose ps

# 查看服务日志
docker-compose logs

# 实时查看服务日志
docker-compose logs -f

# 查看指定服务日志
docker-compose logs -f nginx

# 进入指定服务容器
docker-compose exec nginx /bin/bash

# 构建或重新构建服务
docker-compose build

# 拉取服务镜像
docker-compose pull

# 重启服务
docker-compose restart

# 重启指定服务
docker-compose restart nginx

容器化部署实战

下面以一个PHP博客系统为例,演示如何使用Docker进行容器化部署。

项目结构

blog/
├── docker-compose.yml      # Docker Compose配置文件
├── nginx/
│   ├── conf/
│   │   └── default.conf    # Nginx配置
│   └── logs/               # Nginx日志目录
├── php/
│   ├── Dockerfile           # PHP镜像构建文件
│   └── php.ini              # PHP配置
├── mysql/
│   ├── conf/
│   │   └── my.cnf           # MySQL配置
│   └── data/                # MySQL数据目录
├── redis/
│   ├── redis.conf           # Redis配置
│   └── data/                # Redis数据目录
└── www/                      # 网站代码目录
    └── index.php

Nginx配置(nginx/conf/default.conf)

server {
    listen 80;
    server_name localhost;
    root /var/www/html;
    index index.php index.html index.htm;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        fastcgi_pass php:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

    location ~ /\.(ht|git|svn) {
        deny all;
    }
}

PHP Dockerfile(php/Dockerfile)

FROM php:7.4-fpm

RUN apt-get update && apt-get install -y \
    git \
    unzip \
    libpng-dev \
    libjpeg-dev \
    libfreetype6-dev \
    && docker-php-ext-configure gd --with-freetype --with-jpeg \
    && docker-php-ext-install gd pdo pdo_mysql mysqli \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

WORKDIR /var/www/html

CMD ["php-fpm"]

docker-compose.yml

version: '3.8'

services:
  nginx:
    image: nginx:1.21
    container_name: blog-nginx
    ports:
      - "80:80"
    volumes:
      - ./nginx/conf:/etc/nginx/conf.d
      - ./nginx/logs:/var/log/nginx
      - ./www:/var/www/html
    depends_on:
      - php
    networks:
      - blog-network
    restart: always

  php:
    build: ./php
    container_name: blog-php
    volumes:
      - ./www:/var/www/html
      - ./php/php.ini:/usr/local/etc/php/php.ini
    depends_on:
      - mysql
      - redis
    networks:
      - blog-network
    restart: always

  mysql:
    image: mysql:5.7
    container_name: blog-mysql
    ports:
      - "3306:3306"
    volumes:
      - ./mysql/data:/var/lib/mysql
      - ./mysql/conf:/etc/mysql/conf.d
    environment:
      MYSQL_ROOT_PASSWORD: root123456
      MYSQL_DATABASE: blog_db
      MYSQL_USER: blog_user
      MYSQL_PASSWORD: blog123456
    networks:
      - blog-network
    restart: always

  redis:
    image: redis:6.2
    container_name: blog-redis
    ports:
      - "6379:6379"
    volumes:
      - ./redis/data:/data
      - ./redis/redis.conf:/etc/redis/redis.conf
    command: redis-server /etc/redis/redis.conf
    networks:
      - blog-network
    restart: always

networks:
  blog-network:
    driver: bridge

部署步骤

# 1. 进入项目目录
cd blog

# 2. 启动所有服务
docker-compose up -d

# 3. 查看服务状态
docker-compose ps

# 4. 查看服务日志
docker-compose logs -f

# 5. 访问网站
# 浏览器访问 http://localhost

# 6. 停止服务
docker-compose stop

# 7. 停止并删除容器
docker-compose down

Docker最佳实践

1. 镜像优化

  • 使用轻量级基础镜像,如alpine
  • 合并RUN指令,减少镜像层数
  • 清理缓存和临时文件,减小镜像体积
  • 使用多阶段构建,只保留运行时需要的文件
  • 合理使用.dockerignore,排除不需要的文件

2. 容器安全

  • 不要以root用户运行容器,使用非root用户
  • 不要在镜像中存放敏感信息,使用环境变量或Secret
  • 定期更新基础镜像,修复安全漏洞
  • 限制容器的资源使用(CPU、内存)
  • 不要使用--privileged特权模式,除非必要

3. 数据持久化

  • 重要数据使用数据卷持久化,不要存在容器内
  • 定期备份数据卷
  • 数据库容器使用数据卷存储数据

4. 日志管理

  • 容器日志输出到stdout/stderr,不要写入文件
  • 使用日志驱动收集和管理日志
  • 定期清理日志,避免磁盘占满

5. 编排管理

  • 使用Docker Compose管理多容器应用
  • 生产环境使用Kubernetes等容器编排工具
  • 合理划分服务,一个容器一个进程
  • 使用健康检查,确保服务正常运行

总结

Docker是现代开发者的必备技能,它彻底改变了软件的开发、分发和部署方式。通过Docker,我们可以实现环境一致性、快速部署、轻量级虚拟化、可移植性、隔离性、可扩展性等优势。

本文介绍了Docker的基本概念、安装、基本命令、Dockerfile、Docker Compose以及容器化部署实战,希望能帮助大家快速上手Docker。

Docker的功能远不止这些,还有很多高级功能等待我们去探索和学习,如Docker Swarm、Kubernetes、服务网格、CI/CD集成等。掌握Docker,能让我们的开发和部署工作更加高效、可靠。

容器化是未来的趋势,让我们拥抱Docker,拥抱容器化,让开发和部署变得更加简单和高效。