Skip to main content

Creating PostgreSQL service containers

You can create a PostgreSQL service container to use in your workflow. This guide shows examples of creating a PostgreSQL service for jobs that run in containers or directly on the runner machine.

Introduction

This guide shows you workflow examples that configure a service container using the Docker Hub postgres image. The workflow runs a script that connects to the PostgreSQL service, creates a table, and then populates it with data. To test that the workflow creates and populates the PostgreSQL table, the script prints the data from the table to the console.

注意

如果工作流使用 Docker 容器操作、作业容器或服务容器,则必须使用 Linux 运行器:

  • 如果您要使用 GitHub 托管的运行器,则必须使用 Ubuntu 运行器。
  • 如果您要使用自托管运行器,则必须使用 Linux 机器作为运行器,并且必须安装 Docker。

Prerequisites

您应该熟悉服务容器如何与 GitHub Actions 协同作用,以及直接在运行器上或在容器中运行任务之间的网络差异。 有关详细信息,请参阅“关于服务容器”。

You may also find it helpful to have a basic understanding of YAML, the syntax for GitHub Actions, and PostgreSQL. For more information, see:

Running jobs in containers

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

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

YAML
name: PostgreSQL service 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
      postgres:
        # Docker Hub image
        image: postgres
        # Provide the password for postgres
        env:
          POSTGRES_PASSWORD: postgres
        # Set health checks to wait until postgres has started
        options: >-
          --health-cmd pg_isready
          --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@v4

      # 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 PostgreSQL
        # Runs a script that creates a PostgreSQL table, populates
        # the table with data, and then retrieves the data.
        run: node client.js
        # Environment variables used by the `client.js` script to create a new PostgreSQL table.
        env:
          # The hostname used to communicate with the PostgreSQL service container
          POSTGRES_HOST: postgres
          # The default PostgreSQL port
          POSTGRES_PORT: 5432

Configuring the runner job for jobs in containers

此工作流配置在 node:20-bookworm-slim 容器中运行的作业,并使用 ubuntu-latest GitHub 托管的 运行器作为容器的 Docker 主机。 有关 node:20-bookworm-slim 容器的详细信息,请参阅 Docker Hub 上的此节点映像

工作流用 postgres 标签配置服务容器。 所有服务必须在容器中运行,因此每项服务都需要指定容器 image。 此示例使用 postgres 容器映像,提供默认的 PostgreSQL 密码,并包括状态检查选项以确保服务正在运行。 有关详细信息,请参阅 Docker Hub 上的 postgres 映像

YAML
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
      postgres:
        # Docker Hub image
        image: postgres
        # Provide the password for postgres
        env:
          POSTGRES_PASSWORD: postgres
        # Set health checks to wait until postgres has started
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5

Configuring the steps for jobs in containers

工作流程执行以下步骤:

  1. 检出运行器上的仓库
  2. 安装依赖项
  3. 运行脚本来创建客户端
YAML
steps:
  # Downloads a copy of the code in your repository before running CI tests
  - name: Check out repository code
    uses: actions/checkout@v4

  # 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 PostgreSQL
    # Runs a script that creates a PostgreSQL table, populates
    # the table with data, and then retrieves the data.
    run: node client.js
    # Environment variable used by the `client.js` script to create
    # a new PostgreSQL client.
    env:
      # The hostname used to communicate with the PostgreSQL service container
      POSTGRES_HOST: postgres
      # The default PostgreSQL port
      POSTGRES_PORT: 5432

client.js 脚本查找 POSTGRES_HOSTPOSTGRES_PORT 环境变量以创建客户端。 工作流将这两个环境变量设置为“连接到 PostgreSQL”步骤的一部分,以使它们可供 client.js 脚本使用。 有关脚本的详细信息,请参阅测试 PostgreSQL 服务容器

The hostname of the PostgreSQL service is the label you configured in your workflow, in this case, postgres. Because Docker containers on the same user-defined bridge network open all ports by default, you'll be able to access the service container on the default PostgreSQL port 5432.

Running jobs directly on the runner machine

When you run a job directly on the runner machine, you'll need to map the ports on the service container to ports on the Docker host. You can access service containers from the Docker host using localhost and the Docker host port number.

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

YAML
name: PostgreSQL Service 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
      postgres:
        # Docker Hub image
        image: postgres
        # Provide the password for postgres
        env:
          POSTGRES_PASSWORD: postgres
        # Set health checks to wait until postgres has started
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          # Maps tcp port 5432 on service container to the host
          - 5432:5432

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

      # 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 PostgreSQL
        # Runs a script that creates a PostgreSQL table, populates
        # the table with data, and then retrieves the data
        run: node client.js
        # Environment variables used by the `client.js` script to create
        # a new PostgreSQL table.
        env:
          # The hostname used to communicate with the PostgreSQL service container
          POSTGRES_HOST: localhost
          # The default PostgreSQL port
          POSTGRES_PORT: 5432

Configuring the runner job for jobs directly on the runner machine

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

工作流用 postgres 标签配置服务容器。 所有服务必须在容器中运行,因此每项服务都需要指定容器 image。 此示例使用 postgres 容器映像,提供默认的 PostgreSQL 密码,并包括状态检查选项以确保服务正在运行。 有关详细信息,请参阅 Docker Hub 上的 postgres 映像

The workflow maps port 5432 on the PostgreSQL service container to the Docker host. For more information about the ports keyword, see 关于服务容器.

YAML
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
      postgres:
        # Docker Hub image
        image: postgres
        # Provide the password for postgres
        env:
          POSTGRES_PASSWORD: postgres
        # Set health checks to wait until postgres has started
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          # Maps tcp port 5432 on service container to the host
          - 5432:5432

Configuring the steps for jobs directly on the runner machine

工作流程执行以下步骤:

  1. 检出运行器上的仓库
  2. 安装依赖项
  3. 运行脚本来创建客户端
YAML
steps:
  # Downloads a copy of the code in your repository before running CI tests
  - name: Check out repository code
    uses: actions/checkout@v4

  # 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 PostgreSQL
    # Runs a script that creates a PostgreSQL table, populates
    # the table with data, and then retrieves the data
    run: node client.js
    # Environment variables used by the `client.js` script to create
    # a new PostgreSQL table.
    env:
      # The hostname used to communicate with the PostgreSQL service container
      POSTGRES_HOST: localhost
      # The default PostgreSQL port
      POSTGRES_PORT: 5432

client.js 脚本查找 POSTGRES_HOSTPOSTGRES_PORT 环境变量以创建客户端。 工作流将这两个环境变量设置为“连接到 PostgreSQL”步骤的一部分,以使它们可供 client.js 脚本使用。 有关脚本的详细信息,请参阅测试 PostgreSQL 服务容器

主机名为 localhost127.0.0.1

Testing the PostgreSQL service container

You can test your workflow using the following script, which connects to the PostgreSQL service and adds a new table with some placeholder data. The script then prints the values stored in the PostgreSQL table to the terminal. Your script can use any language you'd like, but this example uses Node.js and the pg npm module. For more information, see the npm pg module.

You can modify client.js to include any PostgreSQL operations needed by your workflow. In this example, the script connects to the PostgreSQL service, adds a table to the postgres database, inserts some placeholder data, and then retrieves the data.

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

JavaScript
const { Client } = require('pg');

const pgclient = new Client({
    host: process.env.POSTGRES_HOST,
    port: process.env.POSTGRES_PORT,
    user: 'postgres',
    password: 'postgres',
    database: 'postgres'
});

pgclient.connect();

const table = 'CREATE TABLE student(id SERIAL PRIMARY KEY, firstName VARCHAR(40) NOT NULL, lastName VARCHAR(40) NOT NULL, age INT, address VARCHAR(80), email VARCHAR(40))'
const text = 'INSERT INTO student(firstname, lastname, age, address, email) VALUES($1, $2, $3, $4, $5) RETURNING *'
const values = ['Mona the', 'Octocat', 9, '88 Colin P Kelly Jr St, San Francisco, CA 94107, United States', '[email protected]']

pgclient.query(table, (err, res) => {
    if (err) throw err
});

pgclient.query(text, values, (err, res) => {
    if (err) throw err
});

pgclient.query('SELECT * FROM student', (err, res) => {
    if (err) throw err
    console.log(err, res.rows) // Print the data in student table
    pgclient.end()
});

The script creates a new connection to the PostgreSQL service, and uses the POSTGRES_HOST and POSTGRES_PORT environment variables to specify the PostgreSQL service IP address and port. If host and port are not defined, the default host is localhost and the default port is 5432.

The script creates a table and populates it with placeholder data. To test that the postgres database contains the data, the script prints the contents of the table to the console log.

When you run this workflow, you should see the following output in the "Connect to PostgreSQL" step, which confirms that you successfully created the PostgreSQL table and added data:

null [ { id: 1,
    firstname: 'Mona the',
    lastname: 'Octocat',
    age: 9,
    address:
     '88 Colin P Kelly Jr St, San Francisco, CA 94107, United States',
    email: '[email protected]' } ]