覆盖容器默认设置
说明
当 Docker 容器启动时,它会执行一个应用程序或命令。容器从其镜像的配置中获取此可执行文件(脚本或文件)。容器带有通常运行良好的默认设置,但如果需要,你可以更改它们。这些调整有助于容器中的程序按你期望的方式精确运行。
例如,如果你有一个监听标准端口的现有数据库容器,并且你想运行同一数据库容器的新实例,那么你可能需要更改新容器监听的端口设置,以避免与现有容器冲突。有时,如果程序需要更多资源来处理繁重的工作负载,你可能需要增加容器可用的内存,或者设置环境变量以提供程序正常运行所需的特定配置详细信息。
docker run
命令提供了一种强大的方式来覆盖这些默认设置,并根据你的喜好调整容器的行为。该命令提供了几个标志,允许你动态自定义容器行为。
以下是一些实现方法。
覆盖网络端口
有时,你可能希望为开发和测试目的使用独立的数据库实例。在同一端口上运行这些数据库实例可能会发生冲突。你可以在 docker run
命令中使用 -p
选项将容器端口映射到主机端口,从而允许你在不发生任何冲突的情况下运行容器的多个实例。
$ docker run -d -p HOST_PORT:CONTAINER_PORT postgres
设置环境变量
此选项在容器内部设置环境变量 foo
,其值为 bar
。
$ docker run -e foo=bar postgres env
你将看到如下输出
HOSTNAME=2042f2e6ebe4
foo=bar
提示
.env
文件是一种方便的方式来为你的 Docker 容器设置环境变量,而无需在命令行中堆砌大量的-e
标志。要使用.env
文件,你可以将--env-file
选项传递给docker run
命令。$ docker run --env-file .env postgres env
限制容器资源消耗
你可以在 docker run
命令中使用 --memory
和 --cpus
标志来限制容器可以使用的 CPU 和内存量。例如,你可以为 Python API 容器设置内存限制,以防止其在你的主机上消耗过多的资源。以下是命令
$ docker run -e POSTGRES_PASSWORD=secret --memory="512m" --cpus="0.5" postgres
此命令将容器内存使用限制为 512MB,并将 CPU 配额定义为 0.5,相当于半个核心。
监控实时资源使用情况
你可以使用
docker stats
命令来监控运行中容器的实时资源使用情况。这有助于你了解分配的资源是否足够或需要调整。
通过有效使用这些 docker run
标志,你可以根据你的特定要求调整容器化应用程序的行为。
动手尝试
在本实践指南中,你将看到如何使用 docker run
命令覆盖容器的默认设置。
- 下载并安装 Docker Desktop。
运行多个 Postgres 数据库实例
使用以下命令启动一个基于 Postgres 镜像的容器
$ docker run -d -e POSTGRES_PASSWORD=secret -p 5432:5432 postgres
这将在后台启动 Postgres 数据库,监听标准的容器端口
5432
,并映射到主机上的端口5432
。启动第二个 Postgres 容器,并映射到不同的端口。
$ docker run -d -e POSTGRES_PASSWORD=secret -p 5433:5432 postgres
这将在后台启动另一个 Postgres 容器,监听容器内的标准 Postgres 端口
5432
,但映射到主机上的端口5433
。你覆盖主机端口只是为了确保这个新容器不会与现有运行的容器冲突。通过在 Docker Desktop Dashboard 中查看 Containers 视图来验证两个容器是否正在运行。
在受控网络中运行 Postgres 容器
默认情况下,容器在运行时会自动连接到一个称为桥接网络的特殊网络。这个桥接网络就像一个虚拟桥梁,允许同一主机上的容器相互通信,同时将它们与外部世界和其他主机隔离开来。它是大多数容器交互的便捷起点。然而,对于特定场景,你可能需要对网络配置进行更多控制。
这就是自定义网络的用武之地。通过在 docker run
命令中传递 --network
标志来创建自定义网络。所有没有指定 --network
标志的容器都连接到默认的桥接网络。
按照以下步骤,了解如何将 Postgres 容器连接到自定义网络。
使用以下命令创建一个新的自定义网络
$ docker network create mynetwork
运行以下命令验证网络
$ docker network ls
此命令列出所有网络,包括新创建的“mynetwork”。
使用以下命令将 Postgres 连接到自定义网络
$ docker run -d -e POSTGRES_PASSWORD=secret -p 5434:5432 --network mynetwork postgres
这将在后台启动 Postgres 容器,映射到主机端口 5434,并连接到
mynetwork
网络。你传递了--network
参数以通过将容器连接到自定义 Docker 网络来覆盖容器的默认设置,从而实现更好的隔离以及与其他容器的通信。你可以使用docker network inspect
命令查看容器是否连接到这个新的桥接网络。默认桥接网络和自定义网络的关键区别
- DNS 解析:默认情况下,连接到默认桥接网络的容器可以相互通信,但只能通过 IP 地址。(除非你使用
--link
选项,该选项被视为遗留功能)。由于各种技术缺陷,不建议在生产环境中使用。在自定义网络上,容器可以通过名称或别名相互解析。 - 隔离性:所有未指定
--network
的容器都连接到默认桥接网络,因此存在风险,因为不相关的容器也能相互通信。使用自定义网络提供了一个范围限定的网络,只有连接到该网络的容器才能通信,从而提供了更好的隔离性。
- DNS 解析:默认情况下,连接到默认桥接网络的容器可以相互通信,但只能通过 IP 地址。(除非你使用
管理资源
默认情况下,容器的资源使用不受限制。然而,在共享系统中,有效管理资源至关重要。重要的是不要让一个运行中的容器消耗过多的主机内存。
这再次体现了 docker run
命令的强大之处。它提供了 --memory
和 --cpus
等标志来限制容器可以使用的 CPU 和内存量。
$ docker run -d -e POSTGRES_PASSWORD=secret --memory="512m" --cpus=".5" postgres
--cpus
标志指定了容器的 CPU 配额。这里设置为半个 CPU 核心 (0.5),而 --memory
标志指定了容器的内存限制。在本例中,设置为 512 MB。
在 Docker Compose 中覆盖默认的 CMD 和 ENTRYPOINT
有时,你可能需要覆盖 Docker 镜像中定义的默认命令 (CMD
) 或入口点 (ENTRYPOINT
),特别是在使用 Docker Compose 时。
创建一个包含以下内容的
compose.yml
文件services: postgres: image: postgres entrypoint: ["docker-entrypoint.sh", "postgres"] command: ["-h", "localhost", "-p", "5432"] environment: POSTGRES_PASSWORD: secret
Compose 文件定义了一个名为
postgres
的服务,该服务使用官方的 Postgres 镜像,设置了一个入口点脚本,并使用密码认证启动容器。运行以下命令启动服务
$ docker compose up -d
此命令启动 Docker Compose 文件中定义的 Postgres 服务。
使用 Docker Desktop Dashboard 验证认证。
打开 Docker Desktop Dashboard,选择 Postgres 容器,然后选择 Exec 进入容器 shell。你可以输入以下命令连接到 Postgres 数据库
# psql -U postgres
注意
PostgreSQL 镜像在本地设置了信任认证,因此当你从 localhost(在同一容器内部)连接时,可能不需要密码。然而,如果从不同的主机/容器连接,则需要密码。
使用 docker run
覆盖默认的 CMD 和 ENTRYPOINT
你也可以使用以下命令直接通过 docker run
命令覆盖默认设置
$ docker run -e POSTGRES_PASSWORD=secret postgres docker-entrypoint.sh -h localhost -p 5432
此命令运行一个 Postgres 容器,设置用于密码认证的环境变量,覆盖默认启动命令,并配置主机名和端口映射。
其他资源
后续步骤
既然你已经了解了如何覆盖容器默认设置,接下来是学习如何持久化容器数据。