我有一些集成测试,为了成功运行,需要运行postgres数据库,通过docker compose进行设置,并且我的go应用程序从main.go
运行。这是我的码头作文:
version: "3.9"
services:
postgres:
image: postgres:12.5
user: postgres
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
POSTGRES_DB: my-db
ports:
- "5432:5432"
volumes:
- data:/var/lib/postgresql/data
- ./initdb:/docker-entrypoint-initdb.d
networks:
default:
driver: bridge
volumes:
data:
driver: local
和我的Github操作如下:
jobs:
unit:
name: Test
runs-on: ubuntu-latest
services:
postgres:
image: postgres:12.5
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
POSTGRES_DB: my-db
ports:
- 5432:5432
env:
GOMODCACHE: "${{ github.workspace }}/.go/mod/cache"
TEST_RACE: true
steps:
- name: Initiate Database
run: psql -f initdb/init.sql postgresql://postgres:password@localhost:5432/my-db
- name: Set up Cloud SDK
uses: google-github-actions/setup-gcloud@v0
- name: Authenticate with GCP
id: auth
uses: "google-github-actions/auth@v0"
with: credentials_json: ${{ secrets.GCP_ACTIONS_SECRET }}
- name: Configure Docker
run: |
gcloud auth configure-docker "europe- docker.pkg.dev,gcr.io,eu.gcr.io"
- name: Set up Docker BuildX
uses: docker/setup-buildx-action@v1
- name: Start App
run: |
VERSION=latest make images
docker run -d -p 3000:3000 -e POSTGRES_DB_URL='//postgres:password@localhost:5432/my-db?sslmode=disable' --name='app' image/app
- name: Tests
env:
POSTGRES_DB_URL: //postgres:password@localhost:5432/my-db?sslmode=disable
GOMODCACHE: ${{ github.workspace }}/.go/pkg/mod
run: |
make test-integration
docker stop app
我的测试在本地运行得很好,用docker-compose up
启动docker compose并从main.go
运行应用程序。然而,在Github操作中,我得到了以下错误:
failed to connect to `host=/tmp user=nonroot database=`: dial error (dial unix /tmp/.s.PGSQL.5432: connect: no such file or directory
我错过了什么?感谢
您缺少的是在Github Actions服务器中设置实际的Postgres客户端(这就是为什么找不到psql工具的原因(。
将其设置为一个步骤。
- name: Install PostgreSQL client
run: |
apt-get update
apt-get install --yes postgresql-client
除此之外,如果您通过docker-compose运行所有内容,您将需要等待postgres启动并运行(健康并接受连接(。
考虑以下docker组成:
version: '3.1'
services:
api:
build: .
depends_on:
- db
ports:
- 8080:8080
environment:
- RUN_UP_MIGRATION=true
- PSQL_CONN_STRING=postgres://gotstock_user:123@host.docker.internal:5432/gotstockapi?sslmode=disable
command: ./entry
db:
image: postgres:9.5-alpine
restart: always
environment:
- POSTGRES_USER=root
- POSTGRES_PASSWORD=password
ports:
- "5432:5432"
volumes:
- ./db:/docker-entrypoint-initdb.d/
有几件事你需要注意。首先,在api
的environment
部分中,我们有PSQL_CONN_STRING=postgres://gotstock_user:123@host.docker.internal:5432/gotstockapi?sslmode=disable
,它是作为env变量传递的数据库的连接字符串。请注意,主机是host.docker.internal
。
此外,我们在api部分中有command: ./entry
。entry
文件包含以下#!/bin/ash
脚本:
#!/bin/ash
NOT_READY=1
while [ $NOT_READY -gt 0 ] # <- loop that waits till postgres is ready to accept connections
do
pg_isready --dbname=gotstockapi --host=host.docker.internal --port=5432 --username=gotstock_user
NOT_READY=$?
sleep 1
done;
./gotstock-api # <- actually executes the build of the api
sleep 10
go test -v ./it # <- executes the integration-tests
最后,为了让psql客户端在上面的脚本中工作,api的docker文件如下所示:
# syntax=docker/dockerfile:1
FROM golang:1.19-alpine3.15
RUN apk add build-base
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download && go mod verify
COPY . .
RUN apk add postgresql-client
RUN go build -o gotstock-api
EXPOSE 8080
请注意安装客户端的RUN apk add postgresql-client
。
黑客攻击快乐
我认为这段代码有不止一个问题。
问题一:在您的代码中,我没有看到您运行docker-compose up
,因此我认为Postgres没有运行。
问题二:在这一行:docker run -d -p 3000:3000 -e POSTGRES_DB_URL='//postgres:password@localhost:5432/my-app?sslmode=disable' --name='app' image/app
您将Postgres的主机指向localhost
,它在您的本地机器上工作。因为本地主机是您的本地计算机。但是,当您使用docker run
时,您不是在本地机器上运行它,而是在docker容器中运行它。localhost指向conmtainer内部。
两者都有可能的解决方案
由于您已经在使用docker compose,我建议您也在那里添加您的测试web服务器。
将您的docker撰写文件更改为:
version: "3.9"
services:
webapp:
build: image/app
environment:
POSTGRES_DB_URL='//postgres:password@postgres:5432/my-app?sslmode=disable'
ports:
- "3000:3000"
depends_on:
- "postgres"
postgres:
image: postgres:12.5
user: postgres
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
POSTGRES_DB: my-app
ports:
- "5432:5432"
volumes:
- data:/var/lib/postgresql/data
- ./initdb:/docker-entrypoint-initdb.d
networks:
default:
driver: bridge
volumes:
data:
driver: local
如果您现在运行docker-compose up
,那么这两项服务都将可用。它应该起作用。虽然我不是github动作专家,所以我可能错过了一些东西。至少像这样,您可以像在CI中一样在本地运行测试,这是我一直认为的一大优势。