Docker 基础

1. 概念

容器是一种虚拟化技术,用于在操作系统级别隔离应用程序和其依赖的运行环境。它将应用程序及其所有依赖项(如库、运行时环境、配置文件等)打包到一个独立的、可移植的单元中,称为容器。容器可以在不同的计算机上运行,而无需担心环境差异和依赖冲突。

Docker 是一种开源的容器化平台,用于构建、部署和运行应用程序。它基于容器化技术,通过将应用程序及其所有依赖项打包到一个独立的、可移植的容器中,实现了应用程序的快速交付、可移植性和可扩展性。

2. Docker 容器虚拟化的优点

Docker 容器虚拟化具有许多优点,使其成为现代应用程序开发和部署的首选解决方案。以下是 Docker 容器虚拟化的一些主要优点:

  • 轻量级和高性能:Docker 容器是基于操作系统级别的虚拟化,与传统的完整虚拟机相比,容器更加轻量级。容器共享宿主机的操作系统内核,因此启动更快、占用更少的资源,并且具有更低的性能开销。
  • 可移植性:Docker 容器提供了一种可移植的应用程序打包和交付方式。容器包含了应用程序及其所有依赖项,可以在不同的环境中运行,无论是开发、测试还是生产环境,都能保持一致的运行行为。
  • 隔离性:Docker 容器提供了隔离的运行环境,使应用程序和其依赖之间相互隔离。每个容器都有自己的文件系统、进程空间和网络接口,使应用程序之间不会相互干扰,减少了依赖冲突和环境差异的问题。
  • 可扩展性:Docker 容器可以根据需要进行水平扩展,以满足不同负载和流量的需求。通过简单地复制和启动多个相同的容器实例,可以实现应用程序的弹性扩展。
  • 简化部署和管理:Docker 提供了一套简单而强大的工具和命令,使应用程序的部署、管理和维护变得更加容易。通过 Docker,可以轻松地创建、启动、停止、暂停和销毁容器,而不会影响其他容器或宿主机系统。
  • 生态系统和社区支持:Docker 拥有庞大的生态系统和活跃的社区支持。有许多公共的镜像注册中心(如 Docker Hub)可供使用,可以方便地获取和共享常用的容器镜像。此外,社区提供了大量的文档、教程和支持资源,使学习和使用 Docker 变得更加容易。

3. Docker 安装

# 如果安装过docker先卸载
sudo yum remove docker docker-common docker-selinux docker-engine -y

# 安装依赖包
sudo yum install -y yum-utils device-mapper-persistent-data lvm2

# 添加国内yum软件源
sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
 
# 安装docker-ce
sudo yum -y install docker-ce
 
# 设置开机启动 Docker CE
sudo systemctl enable docker
sudo systemctl start docker

# 配置国内镜像加速
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{ 
  "registry-mirrors" : 
    [ 
      "https://u5l3r88m.mirror.aliyuncs.com",
      "https://docker.m.daocloud.io",
      "https://docker.udayun.com", 
      "https://noohub.ru", 
      "https://huecker.io",
      "https://dockerhub.timeweb.cloud" 
    ] 
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

# 查看容器版本
docker version
Bash

4. Docker 镜像相关常用命令

4.1. 搜索镜像命令 search

docker search 命令用于在 Docker Hub 上搜索 Docker 镜像。它允许您根据关键字搜索镜像,并获取与搜索条件匹配的镜像列表。

# 格式
docker search [OPTIONS] TERM
# OPTIONS:可选参数,用于进一步定制搜索行为。常用的选项包括 --filter、--format 等。
# TERM:要搜索的关键字或表达式。


# 常用的 docker search 命令示例:
# 搜索特定关键字的镜像:
docker search ubuntu

# 使用过滤器筛选搜索结果:
# 搜索官方镜像
docker search --filter "is-official=true" ubuntu
# 搜索收藏数大于等于600的镜像
docker search --filter "stars=600" ubuntu

# 指定输出格式:
docker search --format "table {{.Name}}\t{{.Description}}" ubuntu
  
# 限制搜索结果的数量:
docker search --limit 5 ubuntu
Bash

4.2. 拉取镜像命令 pull

docker pull 命令用于从 Docker 镜像仓库中拉取(下载)一个或多个镜像到本地系统。

# 格式
docker pull [OPTIONS] NAME[:TAG|@DIGEST]
# OPTIONS:可选参数,用于进一步定制拉取行为。常用的选项包括 --all-tags、--platform 等。
# NAME[:TAG|@DIGEST]:要拉取的镜像的名称、标签或摘要。

# 拉取指定版本的镜像:
docker pull ubuntu:20.04
# 拉取最新版本的镜像:
docker pull ubuntu:latest
Bash

4.3. 查看本地镜像命令 images

# 格式
docker images 或者 docker image ls
 
# 参数
-q : 只显示镜像ID
docker images -q
621ceef7494a
Bash

4.4. 查看镜像详细信息命令 inspect

# 格式
docker inspect [镜像名称或镜像id]
 
# 参数
-f : 格式化输出
docker inspect -f '{{.Id}}' 621ceef7494a
sha256:621ceef7494adfcbe0e523593639f6625795cc0dc91a750629367a8c7b3ccebb
docker inspect -f '{{.ContainerConfig.Hostname}}' redis
16535cfaf84a
Bash

4.5. 登录镜像仓库命令 login

# 格式
docker login 
# 注:默认情况下,docker login登录的是官方仓库,如果登录其他镜像仓库则需要指定镜像仓库的URL连接。
 
# 参数
--username|-u : 指定用户名
--password|-p : 指定密码
 
docker login -u 1426115933
Password: 
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
 
docker login --username=pingk registry.cn-hangzhou.aliyuncs.com
Password: 
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
 
cat .docker/config.json 
{
    "auths": {
        "https://index.docker.io/v1/": {
            "auth": "MTQyNjExNTkzMzpXdTE1NTg4MTk4OTA5LjA="
        },
        "registry.cn-hangzhou.aliyuncs.com": {
            "auth": "5q2m5a6c5biFOld1MTU1ODgxOTg5MDkuMA=="
        }
    }
}
Bash

4.6. 镜像添加标签命令 tag

# 镜像标签的构成
docker.io/library/redis:latest
docker.io  # 镜像仓库的URL
library    # 镜像仓库命名空间
redis      # 镜像名称
latest     # 镜像版本号
 
# 打标签
# 格式
docker tag [镜像ID]  镜像标签
 
# 示例
 
docker tag 621ceef7494a registry.cn-hangzhou.aliyuncs.com/wxyuan/test/redis:v1
Bash

4.7. 上传镜像命令 push

# 格式
docker push [镜像标签]
 
# 注:要想上传镜像,首先得登录镜像仓库,其次设置对应镜像仓库的tag
 
docker push registry.cn-hangzhou.aliyuncs.com/wxyuan/test/redis:v1 
The push refers to repository [registry.cn-hangzhou.aliyuncs.com/wxyuan/test/redis]
3480f9cdd491: Pushed 
a24a292d0184: Pushed 
f927192cc30c: Pushed 
1450b8f0019c: Pushed 
8e14cb7841fa: Pushed 
cb42413394c4: Pushed 
v1: digest: sha256:7ef832c720188ac7898dbd8d1e237b0738e94f94fc7e981cb7b8efe84555e892 size: 1572
Bash

4.8. 删除镜像命令 rmi

# 格式
docker rmi [镜像名称或者镜像ID]

# 示例
docker rmi redis
Untagged: redis:latest
Untagged: redis@sha256:0f97c1c9daf5b69b93390ccbe8d3e2971617ec4801fd0882c72bf7cad3a13494
# 参数
-f  : 强制删除
 
# 示例
docker rmi -f 621ceef7494a
Bash

4.9. 清空本地镜像命令 image prune

docker image prune 命令用于清理不再使用的 Docker 镜像。

# 格式
docker image prune [OPTIONS]
# OPTIONS:可选参数,用于进一步定制清理行为。常用的选项包括 -a、--filter、--force 等。

# 示例
# 清理所有无用的镜像:
docker image prune
# 清理所有无用的镜像及其关联的未使用的镜像层:
docker image prune -a
# 根据过滤条件清理镜像:
# 清理过去24小时未使用的镜像
docker image prune --filter "until=24h"
# 强制清理镜像而不进行确认提示:
docker image prune --force
Bash

4.10. 查看镜像构建历史命令 history

# 格式
docker history [镜像ID或镜像名称]

# 示例
docker pull alpine
Using default tag: latest
latest: Pulling from library/alpine
596ba82af5aa: Pull complete 
Digest: sha256:d9a7354e3845ea8466bb00b22224d9116b183e594527fb5b6c3d30bc01a20378
Status: Downloaded newer image for alpine:latest
docker.io/library/alpine:latest

docker history alpine:latest  
Bash

4.11. 保存容器为镜像命令 commit

# 保存正在运行的容器直接为镜像
# 格式:
docker commit [容器ID|容器名称] 保存名称:版本
 
# 参数
    -a 镜像作者
    -p 提交期间暂停容器
    -m 容器说明
 
# 示例
docker commit -a "xiaowu" -m "小武的容器" -p ebb852aefe0a test:v1
sha256:a9297902755a4ede3ce38c2717515626c678b6deae50206071a0a29ebcd208a9
Bash

4.12. 保存容器为镜像包 export/import

# export保存正在运行的容器为镜像包
## 保存容器为镜像
docker export [容器的ID] > [包名称]
 
# 实例
docker export ebb852aefe0a > nginx:v1.tar
ll
-rw-r--r--  1 root root 135403008 Mar 18 21:05 nginx:v1.tar


# import 将镜像包解为镜像
## docker import [包名称] [自定义镜像名称]
# 实例
docker import nginx:v1.tar  nginx:v2
sha256:59bde51898fa443281782320b194d5e139c37ece32528843bb26d444800265ab
Bash

4.13. 保存镜像为镜像包 save/load

# save保存镜像为镜像包
# 保存镜像的格式:
docker save [镜像名称|镜像ID] > [包名称]
# 示例
docker save alpine > alpine.tar
ll
-rw-r--r--  1 root root   5889024 Mar 18 21:10 alpine.tar
-rw-r--r--  1 root root 135403008 Mar 18 21:05 nginx:v1.tar


# load 将镜像包导入为镜像
docker load < [包名称]
 
# 示例
docker load < alpine.tar 
Loaded image: alpine:latest

# 注:save/load保存镜像无法自定义镜像名称,save保存镜像时如果使用ID保存则load导入镜像无名称,使用名称导入时才有名称
Bash

5. Docker 容器相关常用命令

5.1. 拷贝容器内文件

docker cp 命令只能用于运行中或已停止的容器,不能直接操作镜像内的文件。

# 本地文件拷贝到容器
docker cp /tmp/a.txt test:/usr/share/nginx/html/a.txt 
 
# 容器test的文件拷贝到本地
docker container cp test:/usr/share/nginx/html/a.txt /tmp/
Bash

5.2. 运行容器命令

# 基本语法
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

# 常用选项
## 容器运行模式
-d, --detach  # 后台运行容器
--rm  # 容器退出时自动删除
-it  # 交互式运行(通常组合使用 -i 和 -t)
## 容器命名与标识
--name  # 为容器指定名称
--hostname  # 设置容器主机名
## 网络配置
-p  # 映射容器端口到主机
--network  # 连接容器到指定网络
--dns  # 设置自定义 DNS 服务器
## 资源限制
-m, --memory  # 内存限制
--memory-swap  # 内存+交换分区限制
--cpus  # CPU 数量限制
## 存储与卷
-v, --volume  # 挂载卷
## 环境变量
-e, --env  # 设置环境变量
--env-file  # 从文件读取环境变量
## 安全选项
--user  # 指定运行用户
--read-only  # 以只读模式运行容器


# 使用示例
# 运行一个简单的容器并立即退出
docker run ubuntu echo "Hello World"

# 运行后自动删除容器
docker run --rm alpine echo "This container will self-destruct"

# 以交互模式运行容器
docker run -it ubuntu bash

# 后台运行 Nginx 并映射端口,主机端口:容器端口
docker run -d -p 8080:80 --name mynginx nginx

# 挂载主机目录作为数据卷
docker run -v /host/path:/container/path some-image

# 设置环境变量并限制内存
docker run -e MYVAR=value -m 512m some-image
Bash

5.3. 容器挂载目录与挂载卷

在 Docker 中,挂载目录(Bind Mounts) 和 挂载卷(Volumes) 都是将主机文件系统中的数据映射到容器内部的方式,但它们在实现、管理和使用场景上有重要区别。

  • 挂载目录
    • 直接绑定主机文件系统的某个目录到容器,依赖于主机的文件系统结构。
    • 特点
      • 路径直接映射:必须指定主机的绝对路径和容器的目标路径。
      • 依赖主机目录结构:如果主机目录不存在,Docker 不会自动创建(某些情况下会报错)。
      • 性能较高:直接访问主机文件系统,适合频繁读写的场景。
      • 适合开发调试:修改主机文件会直接影响容器,反之亦然。
    • 适用场景
      • 开发环境(代码热更新)
      • 需要直接修改主机配置文件(如 nginx.conf
      • 共享主机上的特定数据(如日志、临时文件)
    • 使用方式
docker run -v /host/path:/container/path image_name
Bash
  • 挂载卷
    • 由 Docker 管理的存储方式,存储在 Docker 的存储目录(/var/lib/docker/volumes/),与主机文件系统隔离。
    • 特点
      • Docker 管理:卷由 Docker 创建和管理,不依赖主机路径。
      • 自动创建:如果卷不存在,Docker 会自动创建。
      • 跨容器共享:多个容器可以挂载同一个卷。
      • 备份和迁移方便:支持 docker volume 命令管理(如 docker volume create)。
      • 适合生产环境:更安全,不受主机目录变化影响。
    • 适用场景
      • 数据库存储(如 MySQL、PostgreSQL)
      • 持久化应用数据(如配置文件、用户上传文件)
      • 多个容器共享数据(如日志聚合)
    • 使用方式
docker run -v volume_name:/container/path image_name
Bash

5.4. docker volume 命令

# 创建 Volume
docker volume create [OPTIONS] <VOLUME_NAME>
# 示例:这会创建一个名为 my_volume 的 Docker 卷,存储在 /var/lib/docker/volumes/ 下。
docker volume create my_volume

# 查看已创建的 Volume
docker volume ls
# 输出示例:
DRIVER    VOLUME NAME
local     my_volume

# 查看 Volume 详细信息
docker volume inspect my_volume
# 输出示例:
[
    {
        "CreatedAt": "2023-10-05T12:00:00Z",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/my_volume/_data",
        "Name": "my_volume",
        "Options": {},
        "Scope": "local"
    }
]
# Mountpoint 是卷在主机上的实际存储路径(默认在 /var/lib/docker/volumes/)。

# 删除 Volume
docker volume rm my_volume
# 注意:如果卷正在被容器使用,需先删除容器。

# 高级选项
## 指定驱动(Driver),默认使用 local 驱动,但可以指定其他存储驱动(如 nfs、azurefile)
docker volume create --driver local my_volume
## 添加标签(Labels)
docker volume create --label env=prod db_volume
## 设置权限,某些存储驱动支持权限配置,以 nfs 为例
docker volume create --opt type=nfs --opt device=:/nfs/share --opt o=addr=192.168.1.1 nfs_volume
Bash

5.5. 操作容器相关命令

# 查看容器
docker ps -a  # -a 包括停止运行的容器
docker container ls -a  # 与上述命令功能完全相同

# 进入容器
docker exec -it test sh 
 
# 停止与启动
docker stop test
docker start test
docker restart test
 
# 删除
docker container rm -f test
Bash

6. 制作镜像

构建镜像推荐使用 Dockerfile 文件。Dockerfile 是一个文本文件,包含了一系列用于构建 Docker 镜像的指令。下面详细介绍 Dockerfile 的语法、指令等。

6.1. Dockerfile 基本结构

一个典型的 Dockerfile 包含以下部分:

  • 基础镜像声明
  • 元数据信息
  • 系统依赖安装
  • 应用代码复制
  • 运行时配置

6.2. 常用指令详解

FROM

指定基础镜像,必须是 Dockerfile 的第一条指令(除 ARG 外)。

FROM ubuntu:20.04
# 或者
FROM python:3.9-slim
Dockerfile

LABEL

为镜像添加元数据,以键值对形式表示。

LABEL maintainer="your.email@example.com"
LABEL version="1.0"
LABEL description="This is a custom Docker image"
Dockerfile

RUN

执行命令并创建新的镜像层,常用于安装软件包。

RUN apt-get update && apt-get install -y \
    package1 \
    package2 \
    && rm -rf /var/lib/apt/lists/*
Dockerfile

COPY

把宿主机上 Dockerfile 所在的目录下的某个文件拷贝的容器内。

COPY ./app /app
COPY requirements.txt /tmp/
Dockerfile

ADD

类似于 COPY,但功能更多(支持 URL 和解压 tar 文件)。

ADD https://example.com/file.tar.gz /tmp/
ADD file.tar.gz /tmp/
Dockerfile

WORKDIR

设置工作目录,相当于 cd 命令。

WORKDIR /app
Dockerfile

ENV

设置环境变量。

ENV NODE_ENV=production
ENV APP_PORT=3000
Dockerfile

ARG

定义构建时的变量,构建结束后不会保留。

ARG APP_VERSION=1.0
Dockerfile

EXPOSE

用于声明容器在运行时监听的网络端口,它的主要作用是文档化辅助通信,但不会自动将端口映射到宿主机EXPOSE 只是声明,如果容器内的服务没有真正监听该端口,声明无效。

EXPOSE 80
EXPOSE 443
Dockerfile

CMD

指定容器启动时运行的命令(只能有一个 CMD,多个时最后一个生效)。

CMD ["python", "app.py"]
Dockerfile

ENTRYPOINT

配置容器启动时运行的命令(与 CMD 配合使用)。

ENTRYPOINT ["python"]
CMD ["app.py"]
Dockerfile

VOLUME

创建挂载点,用于持久化数据。启动容器时会在宿主机上自动创建匿名卷,然后关联到下述的容器目录中。

VOLUME /data
# 创建多个匿名卷,然后分别挂载到列表中指定的多个目录下
VOLUME ["/aaa","/bbb","/ccc","/var/www/html","/var/lib/mysql"]
Dockerfile

USER

指定运行容器时的用户名或 UID。

USER appuser
Dockerfile

6.3. 示例

Dockerfile 文件:

# 使用官方Python运行时作为基础镜像
FROM python:3.9-slim

# 设置工作目录
WORKDIR /app

# 设置环境变量
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

# 安装系统依赖
RUN apt-get update \
    && apt-get install -y --no-install-recommends gcc \
    && rm -rf /var/lib/apt/lists/*

# 安装Python依赖
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 复制应用代码
COPY . .

# 暴露端口
EXPOSE 8000

# 运行命令
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "app.wsgi"]
Dockerfile

构建镜像:

docker build -t myapp:latest .
Bash

6.4. Dockerfile 多阶段构建

Docker 17.05 版本以后,支持了多阶段构建,允许一个 Dockerfile 中出现多个 FROM 指令,每个 FROM 对应一个阶段,最后生成的镜像以最后一个 FROM 为准。FROM 指令中能够将前置阶段中的文件拷贝到后边的阶段中。示例:

# 构建阶段
FROM golang:1.16 AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp .

# 运行阶段
FROM scratch
WORKDIR /root/
# 拷贝编译阶段中的编译结果到当前镜像中
COPY --from=builder /app/myapp .
CMD ["./myapp"]

# scratch 是内置关键词,并不是一个真实存在的镜像。FROM scratch 会使用一个完全干净的文件系统,不包含任何文件。因为Go语言编译后不需要运行时,也就不需要安装任何的运行库。FROM scratch可以使得最 后生成的镜像最小化,其中只包含了server程序。
Dockerfile

使用场景:

  • 最大的使用场景是将编译环境和运行环境分离,最终的镜像里只有执行程序就行,其他编译过程需要的包都扔掉了,可以显著精简镜像。
上一篇
下一篇