# 创建 Redis 服务容器

您可以使用服务容器在工作流程中创建 Redis 客户端。 本指南举例说明如何为容器中运行或直接在运行器机器上运行的作业创建 Redis 服务。

## 简介

本指南演示了使用 Docker Hub `redis` 映像配置服务容器的工作流示例。 工作流程运行脚本来创建 Redis 客户端并使用数据填充客户端。 要测试工作流程是否创建并填充 Redis 客户端，脚本会将客户端数据打印到控制台。

> \[!NOTE]
> 如果工作流使用 Docker 容器操作、作业容器或服务容器，则必须使用 Linux 运行器：
>
> * 如果您要使用 GitHub 托管的运行器，则必须使用 Ubuntu 运行器。
> * 如果您要使用自托管运行器，则必须使用 Linux 机器作为运行器，并且必须安装 Docker。

## 先决条件

您应该熟悉服务容器如何与 GitHub Actions 协同作用，以及直接在运行器上或在容器中运行任务之间的网络差异。 有关详细信息，请参阅“[与 Docker 服务容器通信](/zh/actions/using-containerized-services/about-service-containers)”。

你可能会发现，掌握基本的 YAML 语法、GitHub Actions 的语法以及 Redis 基础知识也很有帮助。 有关详细信息，请参阅：

* [撰写工作流程](/zh/actions/learn-github-actions)
* Redis 文档中的“[Redis 入门](https://redis.io/learn/howtos/quick-start)”

## 在容器中运行作业

配置要在容器中运行的作业可简化作业与服务容器之间的网络配置。 同一用户定义的桥接网络上的 Docker 容器互相显示所有端口，因此您无需将任何服务容器端口映射到 Docker 主机。 您可以使用工作流程中配置的标签从作业容器访问服务容器。

你可以将此工作流文件复制到存储库的 `.github/workflows` 目录并根据需要进行修改。

```yaml copy
name: Redis container example
on: push

jobs:
  # Label of the container job
  container-job:
    # Containers must run in Linux based operating systems
    runs-on: ubuntu-latest
    # Docker Hub image that `container-job` executes in
    container: node:20-bookworm-slim

    # Service containers to run with `container-job`
    services:
      # Label used to access the service container
      redis:
        # Docker Hub image
        image: redis
        # Set health checks to wait until redis has started
        options: >-
          --health-cmd "redis-cli ping"
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5

    steps:
      # Downloads a copy of the code in your repository before running CI tests
      - name: Check out repository code
        uses: actions/checkout@v6

      # Performs a clean installation of all dependencies in the `package.json` file
      # For more information, see https://docs.npmjs.com/cli/ci.html
      - name: Install dependencies
        run: npm ci

      - name: Connect to Redis
        # Runs a script that creates a Redis client, populates
        # the client with data, and retrieves data
        run: node client.js
        # Environment variable used by the `client.js` script to create a new Redis client.
        env:
          # The hostname used to communicate with the Redis service container
          REDIS_HOST: redis
          # The default Redis port
          REDIS_PORT: 6379
```

### 配置容器作业

此工作流配置在 `node:20-bookworm-slim` 容器中运行的作业，并使用 `ubuntu-latest`  GitHub 托管的 运行器作为容器的 Docker 主机。 有关 `node:20-bookworm-slim` 容器的详细信息，请参阅 Docker Hub 上的此[节点映像](https://hub.docker.com/_/node)。

工作流用 `redis` 标签配置服务容器。 所有服务必须在容器中运行，因此每项服务都需要指定容器 `image`。 此示例使用 `redis` 容器映像，并包括状态检查选项以确保服务正在运行。 在映像名称上附加一个标签以指定版本，例如 `redis:6`。 有关详细信息，请参阅 Docker Hub 上的 [redis 映像](https://hub.docker.com/_/redis)。

```yaml copy
jobs:
  # Label of the container job
  container-job:
    # Containers must run in Linux based operating systems
    runs-on: ubuntu-latest
    # Docker Hub image that `container-job` executes in
    container: node:20-bookworm-slim

    # Service containers to run with `container-job`
    services:
      # Label used to access the service container
      redis:
        # Docker Hub image
        image: redis
        # Set health checks to wait until redis has started
        options: >-
          --health-cmd "redis-cli ping"
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
```

### 配置容器作业的步骤

工作流程执行以下步骤：

1. 检出运行器上的仓库
2. 安装依赖项
3. 运行脚本来创建客户端

```yaml copy
steps:
  # Downloads a copy of the code in your repository before running CI tests
  - name: Check out repository code
    uses: actions/checkout@v6

  # Performs a clean installation of all dependencies in the `package.json` file
  # For more information, see https://docs.npmjs.com/cli/ci.html
  - name: Install dependencies
    run: npm ci

  - name: Connect to Redis
    # Runs a script that creates a Redis client, populates
    # the client with data, and retrieves data
    run: node client.js
    # Environment variable used by the `client.js` script to create a new Redis client.
    env:
      # The hostname used to communicate with the Redis service container
      REDIS_HOST: redis
      # The default Redis port
      REDIS_PORT: 6379
```

client.js 脚本查找 `REDIS_HOST` 和 `REDIS_PORT` 环境变量以创建客户端。 工作流将这两个环境变量设置为“连接到 Redis”步骤的一部分，以使它们可供 client.js 脚本使用。 有关脚本的详细信息，请参阅[测试 Redis 服务容器](#testing-the-redis-service-container)。

Redis 服务的主机名是您在工作流中配置的标签，在本例中为 `redis`。 由于同一用户定义的网桥网络上的 Docker 容器默认打开所有端口，因此您将能够访问默认 Redis 端口 6379 上的服务容器。

## 直接在运行器机器上运行作业

直接在运行器机器上运行作业时，需要将服务容器上的端口映射到 Docker 主机上的端口。 可以使用 `localhost` 和 Docker 主机端口号从 Docker 主机访问服务容器。

你可以将此工作流文件复制到存储库的 `.github/workflows` 目录并根据需要进行修改。

```yaml copy
name: Redis runner example
on: push

jobs:
  # Label of the runner job
  runner-job:
    # You must use a Linux environment when using service containers or container jobs
    runs-on: ubuntu-latest

    # Service containers to run with `runner-job`
    services:
      # Label used to access the service container
      redis:
        # Docker Hub image
        image: redis
        # Set health checks to wait until redis has started
        options: >-
          --health-cmd "redis-cli ping"
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          # Maps port 6379 on service container to the host
          - 6379:6379

    steps:
      # Downloads a copy of the code in your repository before running CI tests
      - name: Check out repository code
        uses: actions/checkout@v6

      # Performs a clean installation of all dependencies in the `package.json` file
      # For more information, see https://docs.npmjs.com/cli/ci.html
      - name: Install dependencies
        run: npm ci

      - name: Connect to Redis
        # Runs a script that creates a Redis client, populates
        # the client with data, and retrieves data
        run: node client.js
        # Environment variable used by the `client.js` script to create
        # a new Redis client.
        env:
          # The hostname used to communicate with the Redis service container
          REDIS_HOST: localhost
          # The default Redis port
          REDIS_PORT: 6379
```

### 配置运行器作业

示例使用 `ubuntu-latest`  GitHub 托管的 运行器作为 Docker 主机。

工作流用 `redis` 标签配置服务容器。 所有服务必须在容器中运行，因此每项服务都需要指定容器 `image`。 此示例使用 `redis` 容器映像，并包括状态检查选项以确保服务正在运行。 在映像名称上附加一个标签以指定版本，例如 `redis:6`。 有关详细信息，请参阅 Docker Hub 上的 [redis 映像](https://hub.docker.com/_/redis)。

工作流程将 Redis 服务容器上的端口 6379 映射到 Docker 主机。 有关 `ports` 关键字的详细信息，请参阅 [与 Docker 服务容器通信](/zh/actions/using-containerized-services/about-service-containers#mapping-docker-host-and-service-container-ports)。

```yaml copy
jobs:
  # Label of the runner job
  runner-job:
    # You must use a Linux environment when using service containers or container jobs
    runs-on: ubuntu-latest

    # Service containers to run with `runner-job`
    services:
      # Label used to access the service container
      redis:
        # Docker Hub image
        image: redis
        # Set health checks to wait until redis has started
        options: >-
          --health-cmd "redis-cli ping"
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          # Maps port 6379 on service container to the host
          - 6379:6379
```

### 配置运行器作业的步骤

工作流程执行以下步骤：

1. 检出运行器上的仓库
2. 安装依赖项
3. 运行脚本来创建客户端

```yaml copy
steps:
  # Downloads a copy of the code in your repository before running CI tests
  - name: Check out repository code
    uses: actions/checkout@v6

  # Performs a clean installation of all dependencies in the `package.json` file
  # For more information, see https://docs.npmjs.com/cli/ci.html
  - name: Install dependencies
    run: npm ci

  - name: Connect to Redis
    # Runs a script that creates a Redis client, populates
    # the client with data, and retrieves data
    run: node client.js
    # Environment variable used by the `client.js` script to create
    # a new Redis client.
    env:
      # The hostname used to communicate with the Redis service container
      REDIS_HOST: localhost
      # The default Redis port
      REDIS_PORT: 6379
```

client.js 脚本查找 `REDIS_HOST` 和 `REDIS_PORT` 环境变量以创建客户端。 工作流将这两个环境变量设置为“连接到 Redis”步骤的一部分，以使它们可供 client.js 脚本使用。 有关脚本的详细信息，请参阅[测试 Redis 服务容器](#testing-the-redis-service-container)。

主机名为 `localhost` 或 `127.0.0.1`。

## 测试 Redis 服务容器

您可以使用以下脚本测试工作流程，该脚本将创建 Redis 客户端，并使用某些占位符数据填充客户端。 然后，脚本将存储在 Redis 客户端中的值打印到终端。 你的脚本可以使用任何你喜欢的语言，但此示例使用 Node.js 和 `redis` npm 模块。 有关详细信息，请参阅 [npm redis 模块](https://www.npmjs.com/package/redis)。

可以修改 client.js 以包含工作流所需的任何 Redis 操作。 在此示例中，脚本创建 Redis 客户端实例、添加占位符数据，然后检索数据。

使用以下代码将名为 client.js 的新文件添加到存储库。

```javascript copy
const redis = require("redis");

// Creates a new Redis client
// If REDIS_HOST is not set, the default host is localhost
// If REDIS_PORT is not set, the default port is 6379
const redisClient = redis.createClient({
  url: `redis://${process.env.REDIS_HOST}:${process.env.REDIS_PORT}`
});

redisClient.on("error", (err) => console.log("Error", err));

(async () => {
  await redisClient.connect();

  // Sets the key "octocat" to a value of "Mona the octocat"
  const setKeyReply = await redisClient.set("octocat", "Mona the Octocat");
  console.log("Reply: " + setKeyReply);
  // Sets a key to "species", field to "octocat", and "value" to "Cat and Octopus"
  const SetFieldOctocatReply = await redisClient.hSet("species", "octocat", "Cat and Octopus");
  console.log("Reply: " + SetFieldOctocatReply);
  // Sets a key to "species", field to "dinotocat", and "value" to "Dinosaur and Octopus"
  const SetFieldDinotocatReply = await redisClient.hSet("species", "dinotocat", "Dinosaur and Octopus");
  console.log("Reply: " + SetFieldDinotocatReply);
  // Sets a key to "species", field to "robotocat", and "value" to "Cat and Robot"
  const SetFieldRobotocatReply = await redisClient.hSet("species", "robotocat", "Cat and Robot");
  console.log("Reply: " + SetFieldRobotocatReply);

  try {
    // Gets all fields in "species" key
    const replies = await redisClient.hKeys("species");
    console.log(replies.length + " replies:");
    replies.forEach((reply, i) => {
        console.log("    " + i + ": " + reply);
    });
    await redisClient.quit();
  }
  catch (err) {
    // statements to handle any exceptions
  }
})();
```

该脚本使用 `createClient` 方法创建新的 Redis 客户端，该方法接受 `host` 和 `port` 参数。 该脚本使用 `REDIS_HOST` 和 `REDIS_PORT` 环境变量来设置客户端的 IP 地址和端口。 如果未定义 `host` 和 `port`，则默认主机为 `localhost`，默认端口为 6379。

该脚本使用 `set` 和 `hset` 方法，使用某些键、字段和值填充数据库。 要确认 Redis 客户端是否包含数据，脚本会将数据库的内容打印到控制台日志。

运行此工作流程时，应会在“连接到 Redis”步骤中看到以下输出，确认您创建了 Redis 客户端并添加了数据：

```shell
Reply: OK
Reply: 1
Reply: 1
Reply: 1
3 replies:
    0: octocat
    1: dinotocat
    2: robotocat
```