开发你的 Rust 应用程序
先决条件
- 你已经安装了最新版本的 Docker Desktop。
- 你已经完成了 Docker Desktop 学习中心 的演练,以了解 Docker 概念。
- 你有一个 git 客户端。本节中的示例使用基于命令行的 git 客户端,但你可以使用任何客户端。
概述
在本节中,你将学习如何在 Docker 中使用卷和网络。你还将使用 Docker 构建你的镜像,并使用 Docker Compose 使一切变得更加简单。
首先,你将查看如何在容器中运行数据库,以及如何使用卷和网络来持久化数据,并让你的应用程序与数据库通信。然后,你将把所有内容整合到一个 Compose 文件中,该文件允许你使用一个命令设置并运行本地开发环境。
在容器中运行数据库
你无需下载 PostgreSQL、安装、配置,然后将 PostgreSQL 数据库作为服务运行,而是可以使用 PostgreSQL 的 Docker 官方镜像并在容器中运行它。
在容器中运行 PostgreSQL 之前,创建一个 Docker 可以管理的卷来存储你的持久数据和配置。使用 Docker 提供的命名卷功能,而不是使用绑定挂载。
运行以下命令来创建你的卷。
$ docker volume create db-data
现在创建一个网络,你的应用程序和数据库将使用它来相互通信。该网络称为用户定义的桥接网络,它提供了一个很好的 DNS 查找服务,你可以在创建连接字符串时使用。
$ docker network create postgresnet
现在你可以在容器中运行 PostgreSQL,并连接到之前创建的卷和网络。Docker 会从 Hub 拉取镜像并在本地为你运行它。
在以下命令中,选项 --mount 用于启动带有卷的容器。有关更多信息,请参阅
Docker 卷。
$ docker run --rm -d --mount \
"type=volume,src=db-data,target=/var/lib/postgresql" \
-p 5432:5432 \
--network postgresnet \
--name db \
-e POSTGRES_PASSWORD=mysecretpassword \
-e POSTGRES_DB=example \
postgres:18
现在,确保你的 PostgreSQL 数据库正在运行,并且你可以连接到它。连接到容器内运行的 PostgreSQL 数据库。
$ docker exec -it db psql -U postgres
你应该看到如下输出。
psql (15.3 (Debian 15.3-1.pgdg110+1))
Type "help" for help.
postgres=#
在之前的命令中,你通过将 psql 命令传递给 db 容器登录到 PostgreSQL 数据库。按 ctrl-d 退出 PostgreSQL 交互式终端。
获取并运行示例应用程序
对于示例应用程序,你将使用 Awesome Compose 中 react-rust-postgres 应用程序的后端变体。
-
使用以下命令克隆示例应用程序仓库。
$ git clone https://github.com/docker/docker-rust-postgres -
在克隆的仓库目录中,运行
docker init以创建必要的 Docker 文件。参考以下示例来回答docker init的提示。$ docker init Welcome to the Docker Init CLI! This utility will walk you through creating the following files with sensible defaults for your project: - .dockerignore - Dockerfile - compose.yaml - README.Docker.md Let's get started! ? What application platform does your project use? Rust ? What version of Rust do you want to use? 1.70.0 ? What port does your server listen on? 8000 -
在克隆的仓库目录中,在 IDE 或文本编辑器中打开
Dockerfile以进行更新。docker init处理了 Dockerfile 中的大部分指令,但你需要根据你的独特应用程序进行更新。除了src目录外,此应用程序还包括一个用于初始化数据库的migrations目录。将migrations目录的绑定挂载添加到 Dockerfile 的构建阶段。以下是更新后的 Dockerfile。# syntax=docker/dockerfile:1 # Comments are provided throughout this file to help you get started. # If you need more help, visit the Dockerfile reference guide at # https://docs.docker.com/reference/dockerfile/ ################################################################################ # Create a stage for building the application. ARG RUST_VERSION=1.70.0 ARG APP_NAME=react-rust-postgres FROM rust:${RUST_VERSION}-slim-bullseye AS build ARG APP_NAME WORKDIR /app # Build the application. # Leverage a cache mount to /usr/local/cargo/registry/ # for downloaded dependencies and a cache mount to /app/target/ for # compiled dependencies which will speed up subsequent builds. # Leverage a bind mount to the src directory to avoid having to copy the # source code into the container. Once built, copy the executable to an # output directory before the cache mounted /app/target is unmounted. RUN --mount=type=bind,source=src,target=src \ --mount=type=bind,source=Cargo.toml,target=Cargo.toml \ --mount=type=bind,source=Cargo.lock,target=Cargo.lock \ --mount=type=cache,target=/app/target/ \ --mount=type=cache,target=/usr/local/cargo/registry/ \ --mount=type=bind,source=migrations,target=migrations \ <<EOF set -e cargo build --locked --release cp ./target/release/$APP_NAME /bin/server EOF ################################################################################ # Create a new stage for running the application that contains the minimal # runtime dependencies for the application. This often uses a different base # image from the build stage where the necessary files are copied from the build # stage. # # The example below uses the debian bullseye image as the foundation for running the app. # By specifying the "bullseye-slim" tag, it will also use whatever happens to be the # most recent version of that tag when you build your Dockerfile. If # reproducibility is important, consider using a digest # (e.g., debian@sha256:ac707220fbd7b67fc19b112cee8170b41a9e97f703f588b2cdbbcdcecdd8af57). FROM debian:bullseye-slim AS final # Create a non-privileged user that the app will run under. # See https://docs.docker.com/develop/develop-images/dockerfile_best-practices/ #user ARG UID=10001 RUN adduser \ --disabled-password \ --gecos "" \ --home "/nonexistent" \ --shell "/sbin/nologin" \ --no-create-home \ --uid "${UID}" \ appuser USER appuser # Copy the executable from the "build" stage. COPY --from=build /bin/server /bin/ # Expose the port that the application listens on. EXPOSE 8000 # What the container should run when it is started. CMD ["/bin/server"] -
在克隆的仓库目录中,运行
docker build以构建镜像。$ docker build -t rust-backend-image . -
使用以下选项运行
docker run,以在数据库所在的同一网络上将镜像作为容器运行。$ docker run \ --rm -d \ --network postgresnet \ --name docker-develop-rust-container \ -p 3001:8000 \ -e PG_DBNAME=example \ -e PG_HOST=db \ -e PG_USER=postgres \ -e PG_PASSWORD=mysecretpassword \ -e ADDRESS=0.0.0.0:8000 \ -e RUST_LOG=debug \ rust-backend-image -
使用 curl 测试应用程序,以验证它是否连接到数据库。
$ curl http://localhost:3001/users你应该收到如下响应。
[{ "id": 1, "login": "root" }]
使用 Compose 进行本地开发
当你运行 docker init 时,除了 Dockerfile 外,它还会创建一个 compose.yaml 文件。
这个 Compose 文件非常方便,因为你无需键入所有要传递给 docker run 命令的参数。你可以使用 Compose 文件以声明方式完成这些操作。
在克隆的仓库目录中,在 IDE 或文本编辑器中打开 compose.yaml 文件。docker init 处理了大部分指令的创建,但你需要根据你的独特应用程序进行更新。
你需要在 compose.yaml 文件中更新以下项目:
- 取消注释所有数据库指令。
- 在服务器服务下添加环境变量。
以下是更新后的 compose.yaml 文件。
# Comments are provided throughout this file to help you get started.
# If you need more help, visit the Docker compose reference guide at
# https://docs.docker.com/reference/compose-file/
# Here the instructions define your application as a service called "server".
# This service is built from the Dockerfile in the current directory.
# You can add other services your application may depend on here, such as a
# database or a cache. For examples, see the Awesome Compose repository:
# https://github.com/docker/awesome-compose
services:
server:
build:
context: .
target: final
ports:
- 8000:8000
environment:
- PG_DBNAME=example
- PG_HOST=db
- PG_USER=postgres
- PG_PASSWORD=mysecretpassword
- ADDRESS=0.0.0.0:8000
- RUST_LOG=debug
# The commented out section below is an example of how to define a PostgreSQL
# database that your application can use. `depends_on` tells Docker Compose to
# start the database before your application. The `db-data` volume persists the
# database data between container restarts. The `db-password` secret is used
# to set the database password. You must create `db/password.txt` and add
# a password of your choosing to it before running `docker compose up`.
depends_on:
db:
condition: service_healthy
db:
image: postgres:18
restart: always
user: postgres
secrets:
- db-password
volumes:
- db-data:/var/lib/postgresql
environment:
- POSTGRES_DB=example
- POSTGRES_PASSWORD_FILE=/run/secrets/db-password
expose:
- 5432
healthcheck:
test: ["CMD", "pg_isready"]
interval: 10s
timeout: 5s
retries: 5
volumes:
db-data:
secrets:
db-password:
file: db/password.txt请注意,该文件没有为这两个服务指定网络。当你使用 Compose 时,它会自动创建一个网络并将服务连接到它。有关更多信息,请参阅 Compose 中的网络。
在使用 Compose 运行应用程序之前,请注意此 Compose 文件指定了一个 password.txt 文件来保存数据库的密码。你必须创建此文件,因为它不包含在源仓库中。
在克隆的仓库目录中,创建一个名为 db 的新目录,并在该目录中创建一个名为 password.txt 的文件,其中包含数据库的密码。使用你喜欢的 IDE 或文本编辑器,将以下内容添加到 password.txt 文件中。
mysecretpassword如果你之前运行了任何其他容器,请现在 停止 它们。
现在,运行以下 docker compose up 命令以启动你的应用程序。
$ docker compose up --build
该命令传递了 --build 标志,因此 Docker 将编译你的镜像,然后启动容器。
现在测试你的 API 端点。打开一个新的终端,然后使用 curl 命令向服务器发出请求:
$ curl http://localhost:8000/users
你应该收到以下响应:
[{ "id": 1, "login": "root" }]总结
在本节中,你查看了如何设置 Compose 文件,以使用单个命令运行你的 Rust 应用程序和数据库。
相关信息:
下一步
在下一节中,你将了解如何使用 GitHub Actions 设置 CI/CD 管道。