Ubuntu系统下Docker容器技术实战指南从安装配置到应用部署全面掌握容器化核心技能解决开发环境不一致问题
1. 引言:Docker容器技术概述
Docker是一个开源的容器化平台,它可以将应用程序及其依赖项打包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。
Docker的出现解决了软件开发中的一个重要问题:环境一致性。开发人员经常遇到”在我的机器上可以运行”的问题,而Docker通过容器化技术确保了应用程序在不同环境中的一致运行。
2. Ubuntu系统下Docker的安装与配置
2.1 系统要求
在安装Docker之前,确保你的Ubuntu系统满足以下要求:
- Ubuntu 64位版本
- 支持的Ubuntu版本:Ubuntu 20.04 LTS, Ubuntu 18.04 LTS, Ubuntu 16.04 LTS
- 系统内核版本不低于3.10
可以通过以下命令检查系统内核版本:
uname -r
2.2 卸载旧版本Docker
如果系统中已经安装了旧版本的Docker,需要先卸载:
sudo apt-get remove docker docker-engine docker.io containerd runc
2.3 安装Docker
2.3.1 使用APT仓库安装
- 更新APT包索引:
sudo apt-get update
- 安装依赖包,允许APT通过HTTPS使用仓库:
sudo apt-get 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-get update sudo apt-get install docker-ce docker-ce-cli containerd.io
2.3.2 使用脚本安装
Docker提供了一个便捷的安装脚本,可以快速安装Docker:
curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh
2.4 验证Docker安装
安装完成后,运行以下命令验证Docker是否正确安装:
sudo docker run hello-world
如果看到以下输出,表示Docker已成功安装:
Hello from Docker! This message shows that your installation appears to be working correctly. ...
2.5 配置Docker
2.5.1 将用户添加到docker组
默认情况下,只有root用户和docker组的用户才能运行Docker命令。将当前用户添加到docker组,可以避免每次使用Docker时都需要sudo:
sudo usermod -aG docker $USER
注意:添加用户到docker组后,需要注销并重新登录才能使更改生效。
2.5.2 配置Docker镜像加速器
在中国大陆地区,可以使用Docker镜像加速器来提高镜像下载速度。编辑Docker配置文件:
sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://hub-mirror.c.163.com", "https://mirror.baidubce.com"] } EOF sudo systemctl daemon-reload sudo systemctl restart docker
3. Docker基本命令与操作
3.1 镜像相关命令
3.1.1 搜索镜像
docker search [镜像名]
例如,搜索Ubuntu镜像:
docker search ubuntu
3.1.2 拉取镜像
docker pull [镜像名]:[标签]
例如,拉取Ubuntu 20.04镜像:
docker pull ubuntu:20.04
3.1.3 查看本地镜像
docker images
或者
docker image ls
3.1.4 删除本地镜像
docker rmi [镜像ID或镜像名:标签]
例如:
docker rmi ubuntu:20.04
3.2 容器相关命令
3.2.1 运行容器
docker run [选项] [镜像名]:[标签] [命令]
常用选项:
-d
:后台运行容器-i
:以交互模式运行容器-t
:为容器分配一个伪输入终端--name
:为容器指定一个名称-p
:将容器端口映射到主机端口-v
:将主机目录挂载到容器-e
:设置环境变量
例如,运行一个Ubuntu容器并进入交互式终端:
docker run -it --name my-ubuntu ubuntu:20.04 /bin/bash
3.2.2 查看运行中的容器
docker ps
或者
docker container ls
3.2.3 查看所有容器(包括已停止的)
docker ps -a
3.2.4 停止容器
docker stop [容器ID或容器名]
例如:
docker stop my-ubuntu
3.2.5 启动已停止的容器
docker start [容器ID或容器名]
例如:
docker start my-ubuntu
3.2.6 重启容器
docker restart [容器ID或容器名]
例如:
docker restart my-ubuntu
3.2.7 删除容器
docker rm [容器ID或容器名]
例如:
docker rm my-ubuntu
3.2.8 进入运行中的容器
docker exec -it [容器ID或容器名] /bin/bash
例如:
docker exec -it my-ubuntu /bin/bash
3.2.9 查看容器日志
docker logs [容器ID或容器名]
例如:
docker logs my-ubuntu
4. Docker镜像的创建与管理
4.1 使用Dockerfile创建镜像
Dockerfile是一个文本文件,包含了构建Docker镜像的所有命令。下面是一个简单的Dockerfile示例:
# 基础镜像 FROM ubuntu:20.04 # 维护者信息 MAINTAINER Your Name <your.email@example.com> # 设置环境变量 ENV DEBIAN_FRONTEND=noninteractive # 更新软件包列表并安装软件 RUN apt-get update && apt-get install -y nginx curl && rm -rf /var/lib/apt/lists/* # 复制文件到容器中 COPY index.html /var/www/html/ # 暴露端口 EXPOSE 80 # 启动nginx CMD ["nginx", "-g", "daemon off;"]
4.2 构建镜像
在Dockerfile所在目录下,运行以下命令构建镜像:
docker build -t my-nginx:1.0 .
其中:
-t
:指定镜像的名称和标签.
:指定构建上下文,当前目录
4.3 镜像的导出与导入
4.3.1 导出镜像
docker save -o my-nginx-1.0.tar my-nginx:1.0
4.3.2 导入镜像
docker load -i my-nginx-1.0.tar
4.4 镜像的推送与拉取
4.4.1 登录到Docker Hub
docker login
4.4.2 标记镜像
docker tag my-nginx:1.0 your-dockerhub-username/my-nginx:1.0
4.4.3 推送镜像
docker push your-dockerhub-username/my-nginx:1.0
4.4.4 拉取镜像
docker pull your-dockerhub-username/my-nginx:1.0
5. Docker容器的网络配置
5.1 Docker网络类型
Docker提供了多种网络类型,包括:
- bridge:默认网络类型,容器通过桥接方式连接到主机网络
- host:容器与主机共享网络命名空间
- none:容器没有网络接口
- overlay:用于Swarm集群中的容器通信
- macvlan:为容器分配MAC地址,使其显示为物理网络上的设备
- 自定义网络:用户创建的网络
5.2 查看网络
docker network ls
5.3 创建自定义网络
docker network create --driver bridge my-network
5.4 将容器连接到网络
5.4.1 在创建容器时连接到网络
docker run -d --name my-container --network my-network nginx
5.4.2 将已存在的容器连接到网络
docker network connect my-network my-container
5.5 断开容器与网络的连接
docker network disconnect my-network my-container
5.6 查看网络详情
docker network inspect my-network
5.7 删除网络
docker network rm my-network
5.8 端口映射
将容器端口映射到主机端口:
docker run -d -p 8080:80 --name my-nginx nginx
这会将容器的80端口映射到主机的8080端口。
6. Docker数据卷的使用
6.1 数据卷概述
数据卷是一个可供一个或多个容器使用的特殊目录,它绕过UFS(联合文件系统),可以提供很多有用的特性:
- 数据卷可以在容器之间共享和重用
- 对数据卷的修改会立马生效
- 对数据卷的更新不会影响镜像
- 数据卷默认会一直存在,即使容器被删除
6.2 创建数据卷
docker volume create my-volume
6.3 查看数据卷
docker volume ls
6.4 查看数据卷详情
docker volume inspect my-volume
6.5 使用数据卷
6.5.1 在创建容器时挂载数据卷
docker run -d -v my-volume:/app --name my-container nginx
6.5.2 挂载主机目录到容器
docker run -d -v /host/path:/container/path --name my-container nginx
6.5.3 只读挂载
docker run -d -v my-volume:/app:ro --name my-container nginx
6.6 删除数据卷
docker volume rm my-volume
6.7 清理未使用的数据卷
docker volume prune
7. Docker Compose的使用
7.1 Docker Compose概述
Docker Compose是一个用于定义和运行多容器Docker应用程序的工具。通过Compose,你可以使用YAML文件来配置应用程序需要的所有服务,然后使用一个命令,从YAML文件配置中创建并启动所有服务。
7.2 安装Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose
7.3 验证Docker Compose安装
docker-compose --version
7.4 Docker Compose文件示例
创建一个名为docker-compose.yml
的文件:
version: '3' services: web: build: . ports: - "5000:5000" volumes: - .:/code - logvolume01:/var/log links: - redis redis: image: redis volumes: - logvolume01:/data volumes: logvolume01: {}
7.5 Docker Compose常用命令
7.5.1 启动服务
docker-compose up
后台运行:
docker-compose up -d
7.5.2 停止服务
docker-compose down
7.5.3 查看服务状态
docker-compose ps
7.5.4 查看服务日志
docker-compose logs
7.5.5 构建或重新构建服务
docker-compose build
7.5.6 启动服务
docker-compose start
7.5.7 停止服务
docker-compose stop
7.5.8 重启服务
docker-compose restart
8. 实战案例:使用Docker部署应用
8.1 部署一个简单的Web应用
8.1.1 创建项目目录结构
mkdir my-web-app cd my-web-app mkdir app
8.1.2 创建Flask应用
在app
目录下创建app.py
文件:
from flask import Flask app = Flask(__name__) @app.route('/') def hello(): return "Hello, Dockerized World!" if __name__ == '__main__': app.run(host='0.0.0.0', port=5000)
8.1.3 创建requirements.txt
在项目根目录下创建requirements.txt
文件:
Flask==2.0.1
8.1.4 创建Dockerfile
在项目根目录下创建Dockerfile
文件:
# 基础镜像 FROM python:3.9-slim # 设置工作目录 WORKDIR /app # 复制requirements.txt文件 COPY requirements.txt . # 安装依赖 RUN pip install --no-cache-dir -r requirements.txt # 复制应用代码 COPY ./app /app # 暴露端口 EXPOSE 5000 # 运行应用 CMD ["python", "app.py"]
8.1.5 构建镜像
docker build -t my-web-app .
8.1.6 运行容器
docker run -d -p 5000:5000 --name my-web-app-container my-web-app
8.1.7 测试应用
访问http://localhost:5000
,应该能看到”Hello, Dockerized World!“的输出。
8.2 使用Docker Compose部署多容器应用
8.2.1 创建项目目录结构
mkdir my-multi-app cd my-multi-app mkdir web mkdir db
8.2.2 创建Web应用
在web
目录下创建app.py
文件:
from flask import Flask, jsonify import psycopg2 import os app = Flask(__name__) def get_db_connection(): conn = psycopg2.connect( host="db", database="mydb", user=os.environ['DB_USER'], password=os.environ['DB_PASSWORD'] ) return conn @app.route('/') def hello(): return "Hello, Multi-container World!" @app.route('/users') def get_users(): conn = get_db_connection() cur = conn.cursor() cur.execute('SELECT * FROM users;') users = cur.fetchall() cur.close() conn.close() return jsonify(users) if __name__ == '__main__': app.run(host='0.0.0.0', port=5000)
在web
目录下创建requirements.txt
文件:
Flask==2.0.1 psycopg2-binary==2.9.1
在web
目录下创建Dockerfile
文件:
# 基础镜像 FROM python:3.9-slim # 设置工作目录 WORKDIR /app # 复制requirements.txt文件 COPY requirements.txt . # 安装依赖 RUN pip install --no-cache-dir -r requirements.txt # 复制应用代码 COPY . . # 暴露端口 EXPOSE 5000 # 运行应用 CMD ["python", "app.py"]
8.2.3 创建数据库初始化脚本
在db
目录下创建init.sql
文件:
CREATE DATABASE mydb; c mydb; CREATE TABLE users ( id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, email VARCHAR(255) NOT NULL ); INSERT INTO users (name, email) VALUES ('John Doe', 'john@example.com'); INSERT INTO users (name, email) VALUES ('Jane Smith', 'jane@example.com');
8.2.4 创建Docker Compose文件
在项目根目录下创建docker-compose.yml
文件:
version: '3' services: web: build: ./web ports: - "5000:5000" environment: - DB_USER=postgres - DB_PASSWORD=example depends_on: - db networks: - app-network db: image: postgres:13 environment: - POSTGRES_PASSWORD=example volumes: - ./db/init.sql:/docker-entrypoint-initdb.d/init.sql - postgres_data:/var/lib/postgresql/data networks: - app-network volumes: postgres_data: networks: app-network: driver: bridge
8.2.5 启动应用
docker-compose up -d
8.2.6 测试应用
- 访问
http://localhost:5000
,应该能看到”Hello, Multi-container World!“的输出。 - 访问
http://localhost:5000/users
,应该能看到数据库中的用户列表。
9. Docker在解决开发环境不一致问题中的应用
9.1 开发环境一致性问题
在软件开发过程中,开发环境不一致是一个常见问题。不同的开发人员可能使用不同的操作系统、不同的软件版本或不同的配置,这可能导致”在我的机器上可以运行”的问题。
9.2 使用Docker解决开发环境一致性问题
Docker通过容器化技术提供了一种解决开发环境一致性问题的有效方法。以下是具体实施步骤:
9.2.1 创建开发环境镜像
创建一个包含所有开发工具和依赖的Docker镜像。例如,对于Python开发环境:
# 基础镜像 FROM python:3.9-slim # 设置工作目录 WORKDIR /app # 安装系统依赖 RUN apt-get update && apt-get install -y git vim && rm -rf /var/lib/apt/lists/* # 复制requirements.txt文件 COPY requirements.txt . # 安装Python依赖 RUN pip install --no-cache-dir -r requirements.txt # 复制应用代码 COPY . . # 设置环境变量 ENV PYTHONPATH=/app # 默认命令 CMD ["bash"]
9.2.2 使用Docker Compose管理开发环境
创建一个docker-compose.yml
文件,定义开发环境所需的所有服务:
version: '3' services: app: build: . volumes: - .:/app environment: - FLASK_ENV=development ports: - "5000:5000" depends_on: - db networks: - dev-network db: image: postgres:13 environment: - POSTGRES_PASSWORD=example volumes: - postgres_data:/var/lib/postgresql/data networks: - dev-network volumes: postgres_data: networks: dev-network: driver: bridge
9.2.3 创建开发脚本
创建一个dev.sh
脚本,简化开发环境的启动:
#!/bin/bash # 启动开发环境 docker-compose up -d # 进入应用容器 docker-compose exec app bash
9.2.4 使用VS Code Remote Development
VS Code提供了Remote Development扩展,允许开发者直接在容器中进行开发。以下是配置步骤:
- 在项目根目录创建
.devcontainer
目录。 - 在
.devcontainer
目录下创建devcontainer.json
文件:
{ "name": "Python Development", "dockerFile": "../Dockerfile", "context": "..", "appPort": 5000, "extensions": [ "ms-python.python" ], "settings": { "python.pythonPath": "/usr/local/bin/python", "python.linting.pylintEnabled": true, "python.linting.enabled": true } }
- 在VS Code中安装Remote Development扩展。
- 使用VS Code打开项目,然后点击左下角的绿色远程连接按钮,选择”Reopen in Container”。
9.3 CI/CD中的Docker应用
Docker也可以在CI/CD流程中发挥作用,确保构建、测试和生产环境的一致性。
9.3.1 使用GitHub Actions和Docker
创建一个.github/workflows/ci.yml
文件:
name: CI on: push: branches: [ main ] pull_request: branches: [ main ] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Build the Docker image run: docker build . --file Dockerfile --tag my-app:$(date +%s) - name: Run tests run: docker run my-app:$(date +%s) python -m pytest - name: Login to Docker Hub uses: docker/login-action@v1 with: username: ${{ secrets.DOCKER_HUB_USERNAME }} password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} - name: Push to Docker Hub run: | docker tag my-app:$(date +%s) ${{ secrets.DOCKER_HUB_USERNAME }}/my-app:latest docker push ${{ secrets.DOCKER_HUB_USERNAME }}/my-app:latest
10. 最佳实践和注意事项
10.1 Dockerfile最佳实践
- 使用多阶段构建:减少最终镜像的大小。
# 构建阶段 FROM node:14 AS build WORKDIR /app COPY package*.json ./ RUN npm install COPY . . RUN npm run build # 生产阶段 FROM nginx:alpine COPY --from=build /app/dist /usr/share/nginx/html EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]
- 使用.dockerignore文件:排除不必要的文件和目录。
.git .gitignore node_modules npm-debug.log Dockerfile .dockerignore
- 合并RUN命令:减少镜像层数。
# 不推荐 RUN apt-get update RUN apt-get install -y nginx RUN rm -rf /var/lib/apt/lists/* # 推荐 RUN apt-get update && apt-get install -y nginx && rm -rf /var/lib/apt/lists/*
- 使用特定版本的镜像:避免使用
latest
标签。
# 不推荐 FROM ubuntu:latest # 推荐 FROM ubuntu:20.04
- 以非root用户运行:提高安全性。
FROM node:14 WORKDIR /app COPY package*.json ./ RUN npm install COPY . . RUN groupadd -r appuser && useradd -r -g appuser appuser USER appuser CMD ["node", "app.js"]
10.2 容器安全最佳实践
不要在容器中存储敏感数据:使用环境变量或密钥管理服务。
限制容器资源:防止容器耗尽系统资源。
docker run -d --memory="512m" --cpus="1.0" my-app
定期更新基础镜像:修复已知的安全漏洞。
扫描镜像中的漏洞:使用工具如Docker Security Scanning或Clair。
使用只读根文件系统:防止攻击者修改文件系统。
docker run --read-only my-app
10.3 性能优化
使用缓存层:合理排序Dockerfile中的指令,充分利用缓存。
清理不必要的包和缓存:减少镜像大小。
RUN apt-get update && apt-get install -y nginx && rm -rf /var/lib/apt/lists/* && apt-get clean
使用多阶段构建:减少最终镜像的大小。
选择合适的基础镜像:alpine版本通常比完整版本小得多。
使用.volume:将频繁变化的数据存储在卷中,而不是在镜像中。
10.4 故障排除
- 查看容器日志:
docker logs [容器ID或容器名]
- 检查容器状态:
docker inspect [容器ID或容器名]
- 在容器中运行命令:
docker exec [容器ID或容器名] [命令]
- 查看Docker系统信息:
docker info
- 清理Docker系统:
docker system prune -a
11. 结论
Docker容器技术为软件开发和部署带来了革命性的变化。通过本文的学习,你应该已经掌握了在Ubuntu系统下安装、配置和使用Docker的基本技能,包括创建和管理镜像、运行和管理容器、配置网络和数据卷、使用Docker Compose管理多容器应用,以及如何将Docker应用于解决开发环境不一致问题。
Docker不仅仅是一种技术,更是一种文化和方法论。它提倡”构建一次,到处运行”的理念,极大地简化了软件的开发、测试和部署流程。通过采用Docker容器化技术,开发团队可以更高效地协作,减少环境问题,提高软件交付的速度和质量。
随着云原生技术的发展,Docker已经成为现代软件开发和运维不可或缺的工具。希望本文能够帮助你全面掌握Docker容器技术,并在实际工作中灵活应用,解决实际问题。