Docker实验手册 (CentOS 8)

1. 引言

1.1 Docker简介

在当今的软件开发和部署领域,容器化技术已成为不可或缺的一部分。Docker作为容器技术的领导者,通过提供一种轻量级、可移植、自给自足的打包机制,彻底改变了应用程序的构建、分发和运行方式。它允许开发者将应用程序及其所有依赖项(代码、运行时、系统工具、系统库等)打包到一个独立的镜像中,然后从这个镜像创建容器,确保应用程序在任何环境中都能以相同的方式运行,从而解决了“在我机器上可以运行”的问题。

Docker的核心优势在于其环境一致性快速部署资源隔离高效利用。它极大地简化了开发、测试和生产环境之间的差异,加速了软件交付流程,并为微服务架构和DevOps实践提供了强大的支持。

1.2 实验环境概述 (CentOS 8)

本实验手册将以 CentOS 8 操作系统作为基础环境,详细指导您进行Docker的安装、配置和各项操作。CentOS 8作为一款稳定、企业级的Linux发行版,广泛应用于服务器环境。选择CentOS 8旨在模拟真实的生产环境,让您在实践中更好地理解Docker的部署和管理。

考虑到中国国内的网络环境特点,本手册还将特别强调配置国内镜像加速器的步骤,以确保您在拉取Docker镜像时能够获得流畅的体验。

1.3 实验目的

本实验手册旨在通过一系列详细的实践操作,帮助您全面掌握Docker的核心概念和常用命令,具体目标包括:

通过完成本手册中的所有实验,您将能够自信地在实际项目中运用Docker技术,提升您的开发和运维效率。

2. Docker安装与配置

本章节将详细指导如何在CentOS 8系统上安装Docker Engine,并进行必要的配置,包括国内镜像加速和非root用户使用Docker的设置。这些步骤旨在为后续的Docker实验提供一个稳定且高效的基础环境。

2.1 更换源及Docker镜像加速

为了防止出错,先备份现有的 yum 源文件:

sudo mkdir -p /etc/yum.repos.d/backup
sudo mv /etc/yum.repos.d/*.repo /etc/yum.repos.d/backup/

更换阿里云yum源:

sudo tee /etc/yum.repos.d/CentOS-Base.repo << 'EOF'
[BaseOS]
name=CentOS-$releasever - Base - mirrors.aliyun.com
baseurl=https://mirrors.aliyun.com/centos-vault/8.5.2111/BaseOS/\$basearch/os/
gpgcheck=1
enabled=1
gpgkey=https://mirrors.aliyun.com/centos-vault/8.5.2111/RPM-GPG-KEY-CentOS-Official

[AppStream]
name=CentOS-$releasever - AppStream - mirrors.aliyun.com
baseurl=https://mirrors.aliyun.com/centos-vault/8.5.2111/AppStream/\$basearch/os/
gpgcheck=1
enabled=1
gpgkey=https://mirrors.aliyun.com/centos-vault/8.5.2111/RPM-GPG-KEY-CentOS-Official

[extras]
name=CentOS-$releasever - Extras - mirrors.aliyun.com
baseurl=https://mirrors.aliyun.com/centos-vault/8.5.2111/extras/\$basearch/os/
gpgcheck=1
enabled=1
gpgkey=https://mirrors.aliyun.com/centos-vault/8.5.2111/RPM-GPG-KEY-CentOS-Official
EOF

清除缓存并重建

sudo dnf clean all
sudo dnf makecache

一步修复方案:替换为国内docker源

执行以下命令(逐行复制)👇:

# 1. 删除掉官方 Docker 源
sudo rm -f /etc/yum.repos.d/docker-ce.repo

# 2. 添加阿里云镜像源
sudo tee /etc/yum.repos.d/docker-ce.repo <<-'EOF'
[docker-ce-stable]
name=Docker CE Stable - mirror.aliyun.com
baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/8/x86_64/stable/
enabled=1
gpgcheck=0
EOF

# 3. 清理缓存并刷新源
sudo dnf clean all
sudo dnf makecache

安装docker

sudo dnf install -y docker-ce docker-ce-cli containerd.io

✅ 这会从 mirrors.aliyun.com 下载所有 Docker 相关 RPM 包,国内速度飞快。


启动 Docker 服务

sudo systemctl enable --now docker

测试是否可用:

docker version

若输出 Client/Server 版本号即安装成功。


配置镜像加速

编辑配置文件:

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": [
    "https://docker.1panel.live",
    "https://mirror.ccs.tencentyun.com",
    "https://docker.m.daocloud.io",
    "https://hub-mirror.c.163.com"
  ]
}
EOF

重启服务:

sudo systemctl daemon-reload
sudo systemctl restart docker

验证:

docker info | grep -A3 "Registry Mirrors"

🧰 如果仍然失败(内网或无公网的情况)

你可以:

  1. 手动下载 RPM 包:
    在一台能上网的机器上访问
    https://mirrors.aliyun.com/docker-ce/linux/centos/8/x86_64/stable/Packages/
    下载以下三个包:

    containerd.io-xxxx.rpm
    docker-ce-xxxx.rpm
    docker-ce-cli-xxxx.rpm
    

    然后拷贝到服务器执行:

    sudo dnf localinstall *.rpm -y

2.5 Docker服务管理

了解如何管理Docker服务对于日常维护至关重要。以下是一些常用的systemctl命令,用于管理Docker守护进程:

sudo systemctl start docker
sudo systemctl stop docker
sudo systemctl restart docker
sudo systemctl status docker
sudo systemctl enable docker
sudo systemctl disable docker

3. Docker容器管理

Docker容器是Docker的核心概念,它是一个轻量级、可移植、自给自足的软件包,包含运行应用程序所需的一切:代码、运行时、系统工具、系统库等。本章节将详细介绍如何管理Docker容器的生命周期、进行常用操作、配置网络以及管理数据卷。

3.1 容器生命周期管理

容器的生命周期包括创建、启动、停止、重启和删除等阶段。掌握这些基本命令是进行Docker操作的基础。

3.1.1 创建与启动容器 (docker run)

docker run 命令用于创建并启动一个新的容器。它是Docker中最常用的命令之一,拥有丰富的参数来控制容器的行为。

基本语法

docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

常用选项

实验示例

  1. 运行一个Nginx Web服务器容器
docker run -d -p 8080:80 --name my-nginx nginx:latest
此命令将从Docker Hub拉取`nginx:latest`镜像(如果本地没有),然后在后台运行一个名为`my-nginx`的容器,并将宿主机的8080端口映射到容器的80端口。
  1. 运行一个交互式Ubuntu容器
docker run -it --rm ubuntu:latest bash
此命令将启动一个Ubuntu容器,并进入其bash shell。`-it` 选项使得容器可以交互式运行,`--rm` 选项确保容器退出后自动删除。

3.1.2 查看运行中的容器 (docker ps)

docker ps 命令用于列出当前正在运行的容器。

基本语法

docker ps [OPTIONS]

常用选项

实验示例

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

3.1.3 停止、启动与重启容器 (docker stop, docker start, docker restart)

这些命令用于控制容器的运行状态。

基本语法

docker stop [OPTIONS] CONTAINER [CONTAINER...]
docker start [OPTIONS] CONTAINER [CONTAINER...]
docker restart [OPTIONS] CONTAINER [CONTAINER...]

实验示例

  1. 停止名为my-nginx的容器
docker stop my-nginx
  1. 启动已停止的my-nginx容器
docker start my-nginx
  1. 重启my-nginx容器
docker restart my-nginx

3.1.4 删除容器 (docker rm)

docker rm 命令用于删除一个或多个已停止的容器。

基本语法

docker rm [OPTIONS] CONTAINER [CONTAINER...]

常用选项

实验示例

  1. 删除已停止的my-nginx容器
docker rm my-nginx
  1. 强制删除运行中的容器
docker rm -f my-nginx

3.2 容器操作

除了生命周期管理,Docker还提供了一系列命令来与容器进行交互和监控。

3.2.1 进入容器 (docker exec)

docker exec 命令用于在运行中的容器内部执行命令,常用于进入容器的shell进行调试或配置。

基本语法

docker exec [OPTIONS] CONTAINER COMMAND [ARG...]

常用选项

实验示例

  1. 进入my-nginx容器的bash shell
docker exec -it my-nginx bash
在容器内部,您可以像操作普通Linux系统一样执行命令,例如`ls -l /usr/share/nginx/html`。

3.2.2 查看容器日志 (docker logs)

docker logs 命令用于获取容器的日志输出。

基本语法

docker logs [OPTIONS] CONTAINER

常用选项

实验示例

  1. 查看my-nginx容器的实时日志
docker logs -f my-nginx

3.2.3 查看容器详细信息 (docker inspect)

docker inspect 命令返回Docker对象的低级信息,包括容器、镜像、网络、数据卷等。它以JSON格式输出详细配置。

基本语法

docker inspect [OPTIONS] NAME|ID [NAME|ID...]

实验示例

  1. 查看my-nginx容器的详细信息
docker inspect my-nginx

3.2.4 查看容器内进程 (docker top)

docker top 命令用于查看容器内部运行的进程。

基本语法

docker top CONTAINER [ps OPTIONS]

实验示例

  1. 查看my-nginx容器内的进程
docker top my-nginx

3.2.5 查看容器资源使用 (docker stats)

docker stats 命令用于实时显示一个或多个容器的资源使用情况,包括CPU、内存、网络I/O和块I/O。

基本语法

docker stats [OPTIONS] [CONTAINER...]

常用选项

实验示例

  1. 查看所有运行中容器的资源使用情况
docker stats

3.3 容器网络

Docker提供了强大的网络功能,允许容器之间以及容器与宿主机之间进行通信。Docker默认提供多种网络驱动,如bridgehostnone等,并支持用户自定义网络。

3.3.1 查看网络 (docker network ls)

docker network ls 命令用于列出所有Docker网络。

基本语法

docker network ls [OPTIONS]

实验示例

  1. 列出所有Docker网络
docker network ls

3.3.2 创建自定义网络 (docker network create)

创建自定义网络可以更好地隔离容器,并允许容器通过名称进行通信。

基本语法

docker network create [OPTIONS] NETWORK

常用选项

实验示例

  1. 创建一个名为my-app-network的bridge网络
docker network create my-app-network

3.3.3 连接容器到网络 (docker network connect)

将运行中的容器连接到指定的网络。

基本语法

docker network connect [OPTIONS] NETWORK CONTAINER

实验示例

  1. my-nginx容器连接到my-app-network
docker network connect my-app-network my-nginx

3.3.4 断开容器与网络的连接 (docker network disconnect)

将容器从指定的网络中移除。

基本语法

docker network disconnect [OPTIONS] NETWORK CONTAINER

实验示例

  1. my-nginx容器从my-app-network断开
docker network disconnect my-app-network my-nginx

3.3.5 删除网络 (docker network rm)

删除一个或多个自定义网络。

基本语法

docker network rm NETWORK [NETWORK...]

实验示例

  1. 删除my-app-network
docker network rm my-app-network

3.4 容器数据卷

数据卷是用于持久化Docker容器数据或在容器之间共享数据的首选机制。它独立于容器的生命周期,即使容器被删除,数据卷中的数据也不会丢失。

3.4.1 创建数据卷 (docker volume create)

docker volume create 命令用于创建一个新的数据卷。

基本语法

docker volume create [OPTIONS] VOLUME

实验示例

  1. 创建一个名为my-data的数据卷
docker volume create my-data

3.4.2 查看数据卷 (docker volume ls)

docker volume ls 命令用于列出所有Docker数据卷。

基本语法

docker volume ls [OPTIONS]

实验示例

  1. 列出所有数据卷
docker volume ls

3.4.3 挂载数据卷到容器 (docker run -v)

docker run命令中使用-v选项可以将数据卷挂载到容器内部。

实验示例

  1. 运行一个Nginx容器,并将my-data数据卷挂载到/usr/share/nginx/html
docker run -d -p 8081:80 --name nginx-with-volume -v my-data:/usr/share/nginx/html nginx:latest
现在,`my-data`数据卷中的内容将作为Nginx的网页根目录。
  1. 通过绑定挂载(Bind Mount)将宿主机目录挂载到容器
mkdir -p ~/nginx-html
echo "<h1>Hello from Host!</h1>" > ~/nginx-html/index.html
docker run -d -p 8082:80 --name nginx-bind-mount -v ~/nginx-html:/usr/share/nginx/html nginx:latest
这会将宿主机的`~/nginx-html`目录内容映射到容器的Nginx网页根目录。

3.4.4 查看数据卷详细信息 (docker volume inspect)

docker volume inspect 命令用于查看数据卷的详细信息,包括其挂载点等。

基本语法

docker volume inspect [OPTIONS] VOLUME [VOLUME...]

实验示例

  1. 查看my-data数据卷的详细信息
docker volume inspect my-data

3.4.5 删除数据卷 (docker volume rm)

docker volume rm 命令用于删除一个或多个数据卷。请注意,只有当数据卷没有被任何容器使用时才能被删除。

基本语法

docker volume rm [OPTIONS] VOLUME [VOLUME...]

常用选项

实验示例

  1. 删除my-data数据卷
docker volume rm my-data

3.4.6 清理未使用的本地数据卷 (docker volume prune)

docker volume prune 命令用于删除所有未被任何容器引用的本地数据卷。

基本语法

docker volume prune [OPTIONS]

实验示例

  1. 清理所有未使用的本地数据卷
docker volume prune

通过本章节的学习和实践,您应该已经掌握了Docker容器的基本管理和操作,包括容器的生命周期、交互、监控、网络配置以及数据持久化。这些是构建和管理基于Docker的应用程序的关键技能。

4. Docker镜像管理

Docker镜像是一个轻量级、独立、可执行的软件包,它包含了运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。本章节将详细介绍如何获取、查看、删除、构建、标记、推送以及导入/导出Docker镜像。

4.1 镜像获取 (docker pull)

docker pull 命令用于从远程镜像仓库(默认为Docker Hub)下载镜像到本地。

基本语法

docker pull [OPTIONS] NAME[:TAG|@DIGEST]

常用选项

实验示例

  1. 拉取最新版Ubuntu镜像
docker pull ubuntu:latest
  1. 拉取指定版本的Nginx镜像
docker pull nginx:1.21

4.2 镜像查看 (docker images)

docker imagesdocker image ls 命令用于列出本地主机上的所有镜像。

基本语法

docker images [OPTIONS] [REPOSITORY]

常用选项

实验示例

  1. 列出所有本地镜像
docker images
  1. 只显示镜像ID
docker images -q
  1. 查看特定仓库的镜像
docker images ubuntu

4.3 镜像删除 (docker rmi)

docker rmi 命令用于删除一个或多个本地镜像。

基本语法

docker rmi [OPTIONS] IMAGE [IMAGE...]

常用选项

实验示例

  1. 删除nginx:1.21镜像
docker rmi nginx:1.21
  1. 强制删除一个被容器使用的镜像
docker rmi -f ubuntu:latest
  1. 删除所有悬空镜像(没有被任何标签引用的镜像)
docker image prune

4.4 镜像构建 (docker build)

docker build 命令用于根据Dockerfile文件和上下文构建新的Docker镜像。Dockerfile是一个文本文件,包含了一系列构建镜像的指令。

基本语法

docker build [OPTIONS] PATH | URL | -

常用选项

实验示例

  1. 准备Dockerfile

    首先,创建一个名为my-app的目录,并在其中创建Dockerfile文件和app.py文件。

mkdir -p my-app
cat <<EOF > my-app/Dockerfile
FROM python:3.9-slim-buster
WORKDIR /app
COPY . .
RUN pip install Flask
EXPOSE 5000
CMD ["python", "app.py"]
EOF

echo "Flask" > requirements.txt

cat <<EOF > my-app/app.py
from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello from Docker!"

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)
EOF
  1. 构建镜像

    my-app目录下执行:

docker build -t my-python-app:1.0 my-app
这里的`my-app`表示Dockerfile所在的上下文路径。
  1. 运行构建的镜像
docker run -d -p 5000:5000 --name my-web-app my-python-app:1.0
访问 `http://localhost:5000` 即可看到 "Hello from Docker!"。

4.5 镜像标签与推送 (docker tag, docker push)

docker tag 命令用于为镜像添加一个额外的标签,通常用于将本地镜像标记为准备推送到远程仓库的格式。docker push 命令用于将本地镜像推送到远程镜像仓库。

4.5.1 标记镜像 (docker tag)

基本语法

docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]

实验示例

  1. my-python-app:1.0镜像添加一个新标签,准备推送到Docker Hub

    假设您的Docker Hub用户名为your_dockerhub_username

docker tag my-python-app:1.0 your_dockerhub_username/my-python-app:latest

4.5.2 登录Docker Hub (docker login)

在推送镜像之前,您需要登录到Docker Hub或其他远程仓库。

基本语法

docker login [OPTIONS] [SERVER]

实验示例

  1. 登录Docker Hub
docker login
系统会提示您输入Docker Hub用户名和密码。

4.5.3 推送镜像 (docker push)

基本语法

docker push [OPTIONS] NAME[:TAG]

实验示例

  1. 推送my-python-app镜像到Docker Hub
docker push your_dockerhub_username/my-python-app:latest

4.6 镜像导入导出 (docker save, docker load)

docker savedocker load 命令用于将镜像打包成文件进行传输,或从文件加载镜像。

4.6.1 导出镜像 (docker save)

docker save 命令将一个或多个镜像保存到一个tar归档文件中。

基本语法

docker save [OPTIONS] IMAGE [IMAGE...]

常用选项

实验示例

  1. my-python-app:1.0镜像保存到my-python-app.tar文件
docker save -o my-python-app.tar my-python-app:1.0

4.6.2 导入镜像 (docker load)

docker load 命令从一个tar归档文件或标准输入中加载镜像。

基本语法

docker load [OPTIONS]

常用选项

实验示例

  1. my-python-app.tar文件加载镜像
docker load -i my-python-app.tar

通过本章节的学习和实践,您应该已经掌握了Docker镜像的完整生命周期管理,包括从远程仓库获取、本地查看与删除、通过Dockerfile构建自定义镜像、以及镜像的标记、推送、导入和导出。这些技能是高效利用Docker进行应用部署和分发的基础。

5. Dockerfile

Dockerfile是用于构建Docker镜像的文本文件,它包含了一系列指令,每条指令都在镜像中创建一个层。通过Dockerfile,我们可以自动化镜像的创建过程,实现可重复、版本化的镜像构建。本章节将深入探讨Dockerfile的基本语法、常用指令、构建自定义镜像、多阶段构建以及最佳实践。

5.1 Dockerfile基本语法与指令

Dockerfile中的指令按顺序执行,每条指令都会在镜像中创建一个新的层。以下是一些最常用的Dockerfile指令及其用途。

5.1.1 FROM

FROM 指令指定了新镜像所基于的基础镜像。所有Dockerfile都必须以 FROM 指令开始。

语法FROM <image>[:<tag>] [AS <name>]

FROM ubuntu:22.04
FROM python:3.9-slim-buster AS builder

5.1.2 RUN

RUN 指令用于在当前镜像层上执行命令,并提交结果。它通常用于安装软件包、创建文件或目录等。

语法

RUN apt-get update && apt-get install -y curl
RUN ["/bin/bash", "-c", "echo hello"]

5.1.3 CMD

CMD 指令为执行中的容器提供默认的执行命令。如果 docker run 命令中指定了其他命令,则 CMD 命令会被覆盖。一个Dockerfile中只能有一个 CMD 指令,如果有多个,只有最后一个生效。

语法

CMD ["nginx", "-g", "daemon off;"]
CMD ["python", "app.py"]

5.1.4 ENTRYPOINT

ENTRYPOINT 指令配置容器启动时执行的命令。与 CMD 不同,ENTRYPOINT 不会被 docker run 命令中指定的参数覆盖,而是将这些参数作为 ENTRYPOINT 命令的参数。

语法

ENTRYPOINT ["/usr/bin/cowsay"]
CMD ["hello world"]

运行 docker run my-cowsay-image 会输出 hello world。运行 docker run my-cowsay-image moo 会输出 moo

5.1.5 COPY

COPY 指令将本地文件或目录复制到镜像中的指定路径。

语法COPY [--chown=<user>:<group>] <src>... <dest>

COPY . /app
COPY requirements.txt /tmp/

5.1.6 ADD

ADD 指令与 COPY 类似,但它支持URL和自动解压tar文件。通常推荐使用 COPY,因为它更透明。

语法ADD [--chown=<user>:<group>] <src>... <dest>

ADD http://example.com/latest.tar.gz /tmp/
ADD app.tar.gz /app

5.1.7 WORKDIR

WORKDIR 指令为Dockerfile中后续的 RUN, CMD, ENTRYPOINT, COPY, ADD 指令设置工作目录。

语法WORKDIR /path/to/workdir

WORKDIR /app
COPY . .
RUN ls

5.1.8 EXPOSE

EXPOSE 指令声明容器在运行时监听的端口。它仅仅是声明,并不会实际发布端口,发布端口需要在使用 docker run -p 时指定。

语法EXPOSE <port> [<port>/<protocol>...]

EXPOSE 80
EXPOSE 80/tcp 443/tcp

5.1.9 ENV

ENV 指令设置环境变量,这些变量在构建时和容器运行时都可用。

语法

ENV MY_VAR="hello world"
ENV PATH="$PATH:/usr/local/bin"

5.1.10 VOLUME

VOLUME 指令创建一个挂载点,将宿主机上的目录或另一个容器中的目录挂载到容器中,用于持久化数据或共享数据。

语法VOLUME ["/data"]

VOLUME /var/lib/mysql

5.1.11 USER

USER 指令设置运行 RUN, CMD, ENTRYPOINT 指令的用户或UID。默认情况下,容器以root用户运行。

语法USER <user>[:<group>]

USER appuser

5.1.12 ARG

ARG 指令定义了用户在 docker build 命令中使用 --build-arg <varname>=<value> 标志传递的构建时变量。

语法ARG <name>[=<default value>]

ARG VERSION=1.0
RUN echo "Building version: $VERSION"

5.1.13 LABEL

LABEL 指令为镜像添加元数据,例如维护者信息、版本号等。

语法LABEL <key>="<value>" [<key>="<value>"]...

LABEL maintainer="Your Name <your.email@example.com>"
LABEL version="1.0"

5.2 构建自定义镜像

通过一个实际的例子来演示如何使用Dockerfile构建一个简单的Web应用镜像。

实验目标:构建一个基于Python Flask的Web应用镜像。

  1. 创建项目目录和文件
mkdir my-flask-app
cd my-flask-app

cat <<EOF > Dockerfile
FROM python:3.9-slim-buster
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 5000
CMD ["python3", "app.py"]
EOF

echo "Flask" > requirements.txt

cat <<EOF > app.py
from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello from Flask in Docker!"

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)
EOF
  1. 构建镜像

    my-flask-app目录下执行:

docker build -t my-flask-web-app:1.0 .
这里的`.`表示Dockerfile所在的上下文路径。
  1. 运行容器
docker run -d -p 5000:5000 --name flask-app-container my-flask-web-app:1.0
  1. 验证

    访问 http://localhost:5000http://<your-server-ip>:5000,应该能看到 "Hello from Flask in Docker!"。

5.3 多阶段构建 (Multi-stage builds)

多阶段构建允许您在Dockerfile中使用多个 FROM 语句,每个 FROM 语句可以开始一个新的构建阶段。这使得您可以将构建时所需的工具和依赖项与运行时所需的最终镜像分离开来,从而显著减小最终镜像的大小。

实验目标:使用多阶段构建一个Go语言的Web应用,最终镜像只包含编译后的二进制文件。

  1. 创建项目目录和文件
mkdir my-go-app
cd my-go-app

cat <<EOF > Dockerfile
FROM golang:1.20 AS builder
WORKDIR /app
COPY . .
RUN go mod init my-go-app && go mod tidy
RUN CGO_ENABLED=0 GOOS=linux go build -o my-app .

FROM alpine:latest
WORKDIR /root/
COPY --from=builder /app/my-app .
CMD ["./my-app"]
EOF

cat <<EOF > main.go
package main

import (
	"fmt"
	"log"
	"net/http"
)

func main() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "Hello from Go in Docker!")
	})
	fmt.Println("Server starting on port 8080...")
	log.Fatal(http.ListenAndServe(":8080", nil))
}
EOF
  1. 构建镜像

    my-go-app目录下执行:

docker build -t my-go-web-app:1.0 .
  1. 运行容器
docker run -d -p 8080:8080 --name go-app-container my-go-web-app:1.0
  1. 验证

    访问 http://localhost:8080http://<your-server-ip>:8080,应该能看到 "Hello from Go in Docker!"。

    您还可以比较 golang:1.20 镜像和 alpine:latest 镜像的大小,会发现最终的 my-go-web-app:1.0 镜像非常小。

5.4 Dockerfile最佳实践

编写高效、安全、可维护的Dockerfile是Docker开发的关键。以下是一些推荐的最佳实践:

通过遵循这些最佳实践,您可以创建出更优化、更安全的Docker镜像,从而提升应用程序的部署效率和稳定性。

4. Docker镜像管理

Docker镜像是一个轻量级、独立、可执行的软件包,它包含了运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。本章节将详细介绍如何获取、查看、删除、构建、标记、推送以及导入/导出Docker镜像。

4.1 镜像获取 (docker pull)

docker pull 命令用于从远程镜像仓库(默认为Docker Hub)下载镜像到本地。

基本语法

docker pull [OPTIONS] NAME[:TAG|@DIGEST]

常用选项

实验示例

  1. 拉取最新版Ubuntu镜像
docker pull ubuntu:latest
  1. 拉取指定版本的Nginx镜像
docker pull nginx:1.21

4.2 镜像查看 (docker images)

docker imagesdocker image ls 命令用于列出本地主机上的所有镜像。

基本语法

docker images [OPTIONS] [REPOSITORY]

常用选项

实验示例

  1. 列出所有本地镜像
docker images
  1. 只显示镜像ID
docker images -q
  1. 查看特定仓库的镜像
docker images ubuntu

4.3 镜像删除 (docker rmi)

docker rmi 命令用于删除一个或多个本地镜像。

基本语法

docker rmi [OPTIONS] IMAGE [IMAGE...]

常用选项

实验示例

  1. 删除nginx:1.21镜像
docker rmi nginx:1.21
  1. 强制删除一个被容器使用的镜像
docker rmi -f ubuntu:latest
  1. 删除所有悬空镜像(没有被任何标签引用的镜像)
docker image prune

4.4 镜像构建 (docker build)

docker build 命令用于根据Dockerfile文件和上下文构建新的Docker镜像。Dockerfile是一个文本文件,包含了一系列构建镜像的指令。

基本语法

docker build [OPTIONS] PATH | URL | -

常用选项

实验示例

  1. 准备Dockerfile

    首先,创建一个名为my-app的目录,并在其中创建Dockerfile文件和app.py文件。

mkdir -p my-app
cat <<EOF > my-app/Dockerfile
FROM python:3.9-slim-buster
WORKDIR /app
COPY . .
RUN pip install Flask
EXPOSE 5000
CMD ["python", "app.py"]
EOF

echo "Flask" > requirements.txt

cat <<EOF > my-app/app.py
from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello from Docker!"

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)
EOF
  1. 构建镜像

    my-app目录下执行:

docker build -t my-python-app:1.0 my-app
这里的`my-app`表示Dockerfile所在的上下文路径。
  1. 运行构建的镜像
docker run -d -p 5000:5000 --name my-web-app my-python-app:1.0
访问 `http://localhost:5000` 即可看到 "Hello from Docker!"。

4.5 镜像标签与推送 (docker tag, docker push)

docker tag 命令用于为镜像添加一个额外的标签,通常用于将本地镜像标记为准备推送到远程仓库的格式。docker push 命令用于将本地镜像推送到远程镜像仓库。

4.5.1 标记镜像 (docker tag)

基本语法

docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]

实验示例

  1. my-python-app:1.0镜像添加一个新标签,准备推送到Docker Hub

    假设您的Docker Hub用户名为your_dockerhub_username

docker tag my-python-app:1.0 your_dockerhub_username/my-python-app:latest

4.5.2 登录Docker Hub (docker login)

在推送镜像之前,您需要登录到Docker Hub或其他远程仓库。

基本语法

docker login [OPTIONS] [SERVER]

实验示例

  1. 登录Docker Hub
docker login
系统会提示您输入Docker Hub用户名和密码。

4.5.3 推送镜像 (docker push)

基本语法

docker push [OPTIONS] NAME[:TAG]

实验示例

  1. 推送my-python-app镜像到Docker Hub
docker push your_dockerhub_username/my-python-app:latest

4.6 镜像导入导出 (docker save, docker load)

docker savedocker load 命令用于将镜像打包成文件进行传输,或从文件加载镜像。

4.6.1 导出镜像 (docker save)

docker save 命令将一个或多个镜像保存到一个tar归档文件中。

基本语法

docker save [OPTIONS] IMAGE [IMAGE...]

常用选项

实验示例

  1. my-python-app:1.0镜像保存到my-python-app.tar文件
docker save -o my-python-app.tar my-python-app:1.0

4.6.2 导入镜像 (docker load)

docker load 命令从一个tar归档文件或标准输入中加载镜像。

基本语法

docker load [OPTIONS]

常用选项

实验示例

  1. my-python-app.tar文件加载镜像
docker load -i my-python-app.tar

通过本章节的学习和实践,您应该已经掌握了Docker镜像的完整生命周期管理,包括从远程仓库获取、本地查看与删除、通过Dockerfile构建自定义镜像、以及镜像的标记、推送、导入和导出。这些技能是高效利用Docker进行应用部署和分发的基础。

6. Docker Compose

Docker Compose是一个用于定义和运行多容器Docker应用程序的工具。通过一个YAML文件来配置应用程序的服务,然后使用一个命令即可从配置中创建并启动所有服务。这使得管理复杂的、多服务的应用程序变得非常简单。本章节将介绍Docker Compose的安装、docker-compose.yml文件的编写以及常用命令。

6.1 Docker Compose简介与安装

6.1.1 Docker Compose简介

在实际应用中,一个完整的应用程序往往由多个服务组成,例如Web服务器、数据库、缓存等。这些服务可能需要运行在不同的容器中,并且它们之间需要相互通信。手动管理这些容器(创建、启动、连接)会非常繁琐。Docker Compose正是为了解决这个问题而生,它允许您:

6.1.2 Docker Compose安装

在CentOS 8上,Docker Compose通常作为Docker Engine的一部分,通过docker-compose-plugin包进行安装。如果您在安装Docker Engine时已经包含了此插件,则无需额外安装。您可以通过运行docker compose version命令来验证是否已安装。

docker compose version

如果显示版本信息,则表示已安装。如果未安装,或者您需要安装独立版本的Docker Compose(旧版本),可以按照以下步骤进行:

  1. 下载Docker Compose二进制文件
sudo curl -L "https://github.com/docker/compose/releases/download/v2.23.3/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
**注意**:请根据实际情况替换`v2.23.3`为最新稳定版本。
  1. 添加执行权限
sudo chmod +x /usr/local/bin/docker-compose
  1. 验证安装
docker-compose --version
**注意**:新版本的Docker Compose作为Docker CLI的插件,命令是`docker compose` (无连字符)。旧版本独立安装的命令是`docker-compose` (有连字符)。本手册将主要使用`docker compose`命令。

6.2 docker-compose.yml 文件编写

docker-compose.yml 是Docker Compose的核心配置文件,它使用YAML格式定义了应用程序的服务、网络和数据卷。以下是其主要结构和常用配置项。

6.2.1 文件结构

一个典型的docker-compose.yml文件包含以下顶级键:

6.2.2 services 配置项

services 部分是docker-compose.yml文件中最重要的部分,它定义了应用程序的各个组件。每个服务可以配置以下常用属性:

示例 docker-compose.yml 文件

我们将创建一个包含一个Web服务(Nginx)和一个数据库服务(MySQL)的简单应用。

version: '3.8'

services:
  web:
    image: nginx:latest
    ports:
      - "80:80"
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d
      - ./nginx/html:/usr/share/nginx/html
    depends_on:
      - db
    networks:
      - app-network

  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: root_password
      MYSQL_DATABASE: my_database
    volumes:
      - db_data:/var/lib/mysql
    networks:
      - app-network

networks:
  app-network:
    driver: bridge

volumes:
  db_data:

文件说明

6.3 多容器应用编排

使用docker-compose.yml文件定义好应用程序后,就可以使用docker compose命令来管理整个应用栈。

6.3.1 启动应用 (docker compose up)

docker compose up 命令会根据docker-compose.yml文件创建并启动所有服务。如果服务所需的镜像不存在,它会自动拉取;如果服务容器已存在,它会尝试重建或更新。

基本语法

docker compose up [OPTIONS] [SERVICE...]

常用选项

实验示例

  1. 准备Nginx配置和网页文件

    docker-compose.yml文件同级目录下创建nginx目录,并在其中创建conf.dhtml子目录。

mkdir -p nginx/conf.d
mkdir -p nginx/html

cat <<EOF > nginx/conf.d/default.conf
server {
    listen 80;
    location / {
        root /usr/share/nginx/html;
        index index.html;
    }
}
EOF

cat <<EOF > nginx/html/index.html
<!DOCTYPE html>
<html>
<head>
    <title>Docker Compose Nginx</title>
</head>
<body>
    <h1>Hello from Nginx via Docker Compose!</h1>
    <p>This is a multi-container application example.</p>
</body>
</html>
EOF
  1. 启动应用程序

    在包含docker-compose.yml文件的目录下执行:

docker compose up -d
这将启动 `web` 和 `db` 两个服务。
  1. 验证

    访问 http://localhost:80http://<your-server-ip>:80,应该能看到Nginx提供的网页。

6.3.2 停止并移除应用 (docker compose down)

docker compose down 命令会停止并移除docker-compose.yml文件中定义的所有服务、网络和数据卷(除非数据卷被明确声明为外部的)。

基本语法

docker compose down [OPTIONS]

常用选项

实验示例

  1. 停止并移除应用程序
docker compose down
  1. 停止并移除应用程序,包括数据卷
docker compose down -v

6.3.3 查看服务状态 (docker compose ps)

docker compose ps 命令用于列出Compose项目中所有服务的运行状态。

基本语法

docker compose ps [OPTIONS] [SERVICE...]

实验示例

  1. 查看所有服务的状态
docker compose ps

6.3.4 查看服务日志 (docker compose logs)

docker compose logs 命令用于查看Compose项目中所有服务或指定服务的日志输出。

基本语法

docker compose logs [OPTIONS] [SERVICE...]

常用选项

实验示例

  1. 查看所有服务的实时日志
docker compose logs -f
  1. 查看web服务的日志
docker compose logs web

6.4 Compose常用命令

除了上述命令,Docker Compose还提供了一些其他有用的命令:

docker compose build [SERVICE...]
docker compose start [SERVICE...]
docker compose stop [SERVICE...]
docker compose restart [SERVICE...]
docker compose exec web bash
docker compose config
docker compose pull [SERVICE...]

通过本章节的学习和实践,您应该已经掌握了Docker Compose的基本概念、docker-compose.yml文件的编写以及如何使用docker compose命令来管理多容器应用程序。Docker Compose极大地简化了复杂应用的部署和管理,是Docker生态系统中不可或缺的工具。

7. 总结与展望

7.1 实验回顾

通过本实验手册的学习和实践,您已经全面掌握了Docker在CentOS 8环境下的核心技术。我们从Docker的安装与国内镜像加速配置开始,逐步深入到容器的生命周期管理、交互操作、网络配置和数据持久化。随后,我们探讨了镜像的获取、查看、删除、构建、标记、推送以及导入导出等管理操作。接着,我们学习了如何编写Dockerfile来自动化镜像构建,并了解了多阶段构建的优势和Dockerfile的最佳实践。最后,我们掌握了Docker Compose,通过YAML文件编排和管理多容器应用程序,极大地提升了应用部署和管理的效率。

这些实验不仅覆盖了Docker的常用命令,还通过实际案例帮助您理解了Docker在实际应用中的工作原理和最佳实践。您现在应该能够独立地在CentOS 8系统上部署、管理和维护基于Docker的应用程序。

7.2 Docker生态系统简述

Docker不仅仅是一个容器运行时,它更是一个庞大的生态系统,围绕着容器技术提供了丰富的工具和服务:

7.3 未来学习方向

掌握了Docker的基础知识和实践技能后,您可以进一步探索以下方向,以深化您的容器化技术栈: