找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

1072

积分

0

好友

153

主题
发表于 12 小时前 | 查看: 2| 回复: 0

什么是Docker,为什么要用它

Docker是一个容器化技术,它可以将应用程序及其所有依赖项打包在一个标准化的单元中,即容器。这类似于一个轻量级的虚拟机,但其启动速度更快、资源开销更小。

在容器化普及之前,部署应用时常面临环境不一致的挑战,例如开发、测试、生产环境中的运行时版本(如Python 3.8、3.7、3.9)不匹配。Docker通过将环境与代码一同打包,从根本上解决了“在我机器上能运行”的经典问题。

此外,容器化显著提升了资源利用率。传统方式可能在一台服务器上仅部署单个应用,而利用Docker,可以同时运行多个相互隔离的容器,从而更高效地利用硬件资源。

安装Docker

在Ubuntu系统上安装Docker的步骤如下:

# 更新包索引
sudo apt update
# 安装必要的包
sudo apt install apt-transport-https ca-certificates curl gnupg lsb-release
# 添加Docker官方GPG密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
# 设置稳定版仓库
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 安装Docker Engine
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io

安装完成后,为避免每次执行命令都需sudo,建议将当前用户加入docker组:

sudo usermod -aG docker $USER

执行此命令后,需要重新登录系统或执行 newgrp docker 使配置生效。

对于CentOS系统,安装过程类似,主要区别是使用yum包管理器。Windows和macOS用户可直接下载并安装图形化工具Docker Desktop。

Docker的基本概念

在深入操作前,理解三个核心概念至关重要:

  • 镜像(Image):一个只读模板,包含了运行应用所需的一切:代码、运行时、库、环境变量和配置文件。例如,ubuntu:20.04镜像提供了Ubuntu 20.04操作系统的基本文件系统。
  • 容器(Container):镜像的一个运行实例。你可以从同一个镜像创建多个容器,就像用同一个类实例化多个对象。
  • 仓库(Repository):用于存放镜像的集中存储服务。Docker Hub是全球最大的公共仓库,你也可以搭建私有仓库。

常用Docker命令

镜像相关命令

查看本地已有的镜像:

docker images

image-20251215215521260

从仓库拉取镜像:

docker pull nginx:latest
docker pull ubuntu:20.04

image-20251215215704046

删除本地镜像:

docker rmi nginx:latest

根据当前目录的Dockerfile构建镜像:

docker build -t myapp:v1.0 .

容器相关命令

运行容器:

# 运行测试容器
docker run hello-world
# 以交互模式运行并进入bash
docker run -it ubuntu:20.04 /bin/bash
# 以后台模式运行
docker run -d nginx:latest
# 端口映射:将宿主机8080端口映射到容器80端口
docker run -d -p 8080:80 nginx:latest

查看容器状态:

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

image-20251215215734740

控制容器生命周期:

docker stop container_id
docker start container_id
docker restart container_id

进入正在运行的容器:

docker exec -it container_id /bin/bash

删除容器:

docker rm container_id

查看容器日志:

docker logs container_id
docker logs -f container_id  # 实时跟踪日志

实战案例:部署一个Web应用

让我们通过部署一个简单的基于Python的Flask应用来串联上述概念。

  1. 创建应用文件 app.py
    
    from flask import Flask
    app = Flask(__name__)

@app.route('/')
def hello():
return '<h1>Hello from Docker!</h1>'

@app.route('/health')
def health():
return {'status': 'ok'}

if name == 'main':
app.run(host='0.0.0.0', port=5000)


2.  创建依赖文件 `requirements.txt`:

Flask==2.3.3


3.  编写 `Dockerfile`:
```dockerfile
# 使用Python 3.9精简版作为基础镜像
FROM python:3.9-slim
# 设置工作目录
WORKDIR /app
# 复制依赖文件
COPY requirements.txt .
# 安装依赖
RUN pip install --no-cache-dir -r requirements.txt
# 复制应用代码
COPY app.py .
# 声明容器运行时监听的端口
EXPOSE 5000
# 容器启动命令
CMD ["python", "app.py"]
  1. 构建镜像:

    docker build -t flask-app:v1.0 .
  2. 运行容器:

    docker run -d -p 5000:5000 --name my-flask-app flask-app:v1.0

现在,访问 http://localhost:5000 即可看到运行的应用。这个简单示例涵盖了构建、运行和端口映射等核心操作。

数据持久化和卷(Volume)

容器本质上是无状态的,停止或删除容器后,其内部产生的数据也会丢失。为了实现数据持久化,Docker提供了以下几种方式:

绑定挂载(Bind Mount)

将宿主机的目录或文件直接挂载到容器内。

docker run -d -v /host/path:/container/path nginx:latest

例如,运行MySQL容器时持久化数据:

docker run -d \
  --name mysql-server \
  -e MYSQL_ROOT_PASSWORD=mypassword \
  -v /opt/mysql-data:/var/lib/mysql \
  -p 3306:3306 \
  mysql:8.0

这样,容器内的 /var/lib/mysql 数据将保存在宿主机的 /opt/mysql-data 目录中。

Docker卷(Volume)

由Docker管理的存储方式,比绑定挂载更易于备份和迁移。

# 创建卷
docker volume create mydata
# 使用卷
docker run -d -v mydata:/data nginx:latest
# 查看所有卷
docker volume ls

临时文件系统(tmpfs)

将数据存储在内存中,容器停止后数据即消失,适合存放临时缓存。

docker run -d --tmpfs /tmp nginx:latest

Docker网络详解

Docker的网络功能是实现容器间以及容器与外部世界通信的关键。其底层利用了Linux的网络命名空间实现隔离。

默认网络模式

Docker为容器提供了几种网络模式:

  • bridge模式(默认):容器通过虚拟网桥docker0连接到宿主机网络,拥有独立的IP,可与其他容器通信。
  • host模式:容器直接使用宿主机的网络栈,没有网络隔离,性能最佳。
  • none模式:容器没有任何网络接口,完全隔离。
  • container模式:容器共享另一个容器的网络命名空间。

查看现有网络:

docker network ls

通常会看到 bridgehostnone 三个默认网络。
image-20251215220031477

自定义网络

创建自定义网络能实现更灵活的服务发现和网络策略。

创建并使用自定义bridge网络:

# 创建网络
docker network create mynetwork
# 指定子网的创建方式
docker network create --driver bridge \
  --subnet=172.20.0.0/16 \
  --ip-range=172.20.240.0/20 \
  --gateway=172.20.0.1 \
  mynetwork2
# 在指定网络中运行容器
docker run -d --network mynetwork --name web nginx:latest

关键优势:在自定义网络中,容器可以通过容器名直接相互访问,这解决了默认bridge网络需要通过IP或--link(已不推荐)通信的痛点。

端口映射

将容器内部的端口暴露给宿主机外部访问。

# 基本映射
docker run -d -p 8080:80 nginx:latest
# 映射多个端口
docker run -d -p 8080:80 -p 8443:443 nginx:latest
# 映射到宿主机特定IP
docker run -d -p 127.0.0.1:8080:80 nginx:latest
# 随机映射
docker run -d -P nginx:latest

容器间通信实例:多服务应用

假设我们有一个包含前端、后端和数据库的应用:

# 创建自定义网络
docker network create webapp --subnet=172.18.0.0/16

# 启动数据库(不暴露外部端口)
docker run -d \
  --name database \
  --network webapp \
  -e MYSQL_ROOT_PASSWORD=rootpass \
  mysql:8.0

# 启动后端API(依赖数据库,可通过`database`主机名访问)
docker run -d \
  --name api \
  --network webapp \
  -e DATABASE_HOST=database \
  my-api:latest

# 启动前端(暴露80端口,可通过`api`主机名访问后端)
docker run -d \
  --name frontend \
  --network webapp \
  -p 80:80 \
  -e API_HOST=api \
  my-frontend:latest

此架构实现了服务间通过容器名通信,网络逻辑清晰,且只有前端服务对外暴露端口。

环境变量和配置

为应用注入配置的常用方式:

  1. 命令行直接设置
    docker run -d -e NODE_ENV=production node-app:latest
  2. 使用环境变量文件:创建 .env 文件,内容如 KEY=VALUE,运行命令:
    docker run -d --env-file .env mysql:8.0
  3. 在Dockerfile中定义默认值
    FROM node:16
    ENV NODE_ENV=production
    ENV PORT=3000

Docker Compose:管理多容器应用

当应用由多个服务(如Web、数据库、缓存等)组成时,使用Docker Compose可以通过一个YAML文件定义和运行所有容器。

安装

较新版本的Docker Desktop已内置Compose。Linux系统可单独安装:

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.yml

以下示例定义了一个包含Web应用、MySQL、Redis和Nginx的服务栈,并展示了网络分层设计:

version: '3.8'
services:
  web:
    build: .
    ports:
      - "5000:5000"
    environment:
      - DATABASE_URL=mysql://user:password@db:3306/myapp
      - REDIS_URL=redis://redis:6379
    depends_on:
      - db
      - redis
    networks:
      - backend
  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: rootpassword
    volumes:
      - mysql_data:/var/lib/mysql
    networks:
      - backend
  redis:
    image: redis:7-alpine
    networks:
      - backend
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    depends_on:
      - web
    networks:
      - frontend
networks:
  frontend:
  backend:
    internal: true  # 后端网络禁止外部直接访问
volumes:
  mysql_data:

常用Compose命令

# 启动所有服务
docker-compose up -d
# 查看服务状态
docker-compose ps
# 查看日志
docker-compose logs -f
# 停止并移除所有资源
docker-compose down

生产环境最佳实践

镜像优化

  • 多阶段构建:分离构建环境和运行环境,有效减小最终镜像体积。
  • 选择精简基础镜像:如 alpineslim 版本。
  • 合并RUN指令并清理缓存
    RUN apt-get update && apt-get install -y \
        package1 \
        package2 \
        && rm -rf /var/lib/apt/lists/*
  • 使用 .dockerignore 文件:避免将不必要的文件(如 node_modules, .git)复制进镜像。

安全考虑

  • 避免以root用户运行:在Dockerfile中创建并使用非root用户。
    RUN addgroup -g 1001 -S appgroup && adduser -S appuser -u 1001 -G appgroup
    USER appuser
  • 定期扫描镜像漏洞:使用 docker scan 命令。
  • 配置健康检查:确保应用已就绪。
    HEALTHCHECK --interval=30s --timeout=3s CMD curl -f http://localhost/health || exit 1

日志管理

配置日志驱动,避免日志文件无限增长。

docker run -d \
  --log-driver json-file \
  --log-opt max-size=10m \
  --log-opt max-file=3 \
  nginx:latest

总结

Docker通过容器化技术,为应用提供了从开发到部署的一致性环境,极大地简化了依赖管理和部署流程。本文从核心概念入手,涵盖了安装、基本命令、镜像构建、数据持久化、网络配置等基础内容,并深入探讨了使用Docker Compose编排多服务应用,以及生产环境下的镜像优化、安全与监控等最佳实践。

特别在网络方面,理解并善用自定义网络和容器发现机制,是构建复杂分布式应用的关键。掌握这些知识和实践,将帮助开发者和运维人员更高效地利用容器技术,构建稳定、可扩展的现代化应用架构,这也是现代云原生技术栈的重要基石。




上一篇:Vim命令行文本编辑快速入门:核心模式与快捷键实战指南
下一篇:MCP AI-102高可用部署指南:微服务架构、Kubernetes调度与自动化故障转移
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2025-12-17 15:19 , Processed in 0.108225 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表