PGHOST用于由docker-compose创建的带有docker:dind的GitLab流水线的postgres。

huangapple go评论78阅读模式
英文:

PGHOST for GitLab pipeline with docker:dind for postgres created by docker-compose

问题

我有一个docker-compose文件,用于初始化postgres和用于postgres迁移的服务。我想在GitLab流水线中针对我的docker-compose中的postgres服务运行测试,但我无法通过localhost连接到pg_db。在我的代码中,我使用pgx包。在我的本地机器上,使用localhost作为PGHOST环境变量没有问题。

所以我的主要问题是,在GitLab流水线中,我应该将PGHOST变量设置为什么主机,以便我的测试可以连接到postgres。

docker-compose.yml

version: "3.3"
services:
    pg_db:
      container_name: pg_db
      image: postgres:13.2-alpine
      environment:
        - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
        - POSTGRES_USER=${POSTGRES_USER}
        - POSTGRES_DB=${POSTGRES_DB}
        - POSTGRES_SSLMODE=${POSTGRES_SSLMODE}
        - POSTGRES_HOST_AUTH_METHOD=${POSTGRES_HOST_AUTH_METHOD}
      ports:
        - ${POSTGRES_PORT}:5432
      restart: always
      deploy:
        resources:
          limits:
            cpus: '1'
            memory: 4G
      networks:
        - postgres
        - backend

    #init db
    store-init:
      image: x:latest
      container_name: store-init
      environment:
        - PGHOST=pg_db
        - PGUSER=${POSTGRES_USER}
        - PGPASSWORD=${POSTGRES_PASSWORD}
        - PGDATABASE=${POSTGRES_DB}
        - PGPORT=${POSTGRES_PORT}
      restart: on-failure
      depends_on:
        - pg_db
      networks:
        - postgres
        - backend

networks:
  backend:
  postgres:
    driver: bridge

这是我gitlab-ci.yml的重要部分

services:
    - docker:dind

stages:
  - test

test:
  stage: test
  image: golang:1.17-alpine3.15
  variables:
    PGHOST: localhost
  before_script:
    - apk update && apk add make git openssh g++
    - apk add --no-cache docker-compose
    - git config --global user.email "$GITLAB_USER_EMAIL" && git config --global user.name "$GITLAB_USER_NAME"
    - mkdir -p ~/.ssh && echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa && chmod -R 600 ~/.ssh && ssh-keyscan -t rsa ssh.x >> ~/.ssh/known_hosts
  script:
    - cp .env.example .env
    - docker-compose up -d
    - sleep 30 # a temporary line to get the logs
    - cat /etc/hosts # debug line
    - docker-compose port pg_db 5432 # debug line
    - netstat -a # debug line
    - docker-compose ps # debug line
    - go test -v -timeout 30s ./... -tags=withDB

  only:
    - merge_request
    - dev
    - master

我得到的日志为

variables: 
   PGHOST: localhost
$ cp .env.example .env
$ docker-compose up -d
Recreating alp-logger_pg_db_1 ... 
Recreating alp-logger_pg_db_1 ... done
store-init is up-to-date
$ sleep 30
$ cat /etc/hosts
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.17.0.2	runner-lxzkchpx-project-304-concurrent-0
$ docker-compose port pg_db 5432
0.0.0.0:5432
$ netstat -a
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       
tcp        0      0 runner-lxzkchpx-project-304-concurrent-0:50294 static.124.194.21.65.clients.your-server.de:ssh TIME_WAIT   
Active UNIX domain sockets (servers and established)
Proto RefCnt Flags       Type       State         I-Node Path
$ docker-compose ps
   Name                 Command              State           Ports         
---------------------------------------------------------------------------
pg_db        docker-entrypoint.sh postgres   Up      0.0.0.0:5432->5432/tcp
store-init   ./alp-store                     Up                            

以及连接到postgres数据库的错误:

failed to connect to `host=localhost user=test database=test`: dial error (dial tcp [::1]:5432: connect: cannot assign requested address)

对于

variables: 
    PGHOST: pg_db

和任何其他命名为docker的主机,我得到的错误是:

failed to connect to `host=pg_db user=test database=test`: hostname resolving error (lookup pg_db on 1.1.1.1:53: no such host)

对于

variables: 
    PGHOST: 127.0.0.1

我得到的错误是:

failed to connect to `host=127.0.0.1 user=test database=test`: dial error (dial tcp 127.0.0.1:5432: connect: connection refused)
英文:

I have a docker-compose file, that initializes postgres and service for postgres migration. And I want to run tests in gitlab pipeline against my docker-compose baked postgres service, but I can't connect to pg_db via localhost. Inside my code I use pgx package. On my local machine there is no trouble to use localhost for PGHOST env variable.

So my main question is what host to put in PGHOST variable for my tests to use for postgres connection inside gitlab pipeline.

docker-compose.yml

version: "3.3"
services:
    pg_db:
      container_name: pg_db
      image: postgres:13.2-alpine
      environment:
        - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
        - POSTGRES_USER=${POSTGRES_USER}
        - POSTGRES_DB=${POSTGRES_DB}
        - POSTGRES_SSLMODE=${POSTGRES_SSLMODE}
        - POSTGRES_HOST_AUTH_METHOD=${POSTGRES_HOST_AUTH_METHOD}
      ports:
        - ${POSTGRES_PORT}:5432
      restart: always
      deploy:
        resources:
          limits:
            cpus: '1'
            memory: 4G
      networks:
        - postgres
        - backend

    #init db
    store-init:
      image: x:latest
      container_name: store-init
      environment:
        - PGHOST=pg_db
        - PGUSER=${POSTGRES_USER}
        - PGPASSWORD=${POSTGRES_PASSWORD}
        - PGDATABASE=${POSTGRES_DB}
        - PGPORT=${POSTGRES_PORT}
      restart: on-failure
      depends_on:
        - pg_db
      networks:
        - postgres
        - backend

networks:
  backend:
  postgres:
    driver: bridge

And here is a significant part of my gitlab-ci.yml

services:
    - docker:dind

stages:
  - test

test:
  stage: test
  image: golang:1.17-alpine3.15
  variables:
    PGHOST: localhost
  before_script:
    - apk update && apk add make git openssh g++
    - apk add --no-cache docker-compose
    - git config --global user.email "$GITLAB_USER_EMAIL" && git config --global user.name "$GITLAB_USER_NAME"
    - mkdir -p ~/.ssh && echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa && chmod -R 600 ~/.ssh && ssh-keyscan -t rsa ssh.x >> ~/.ssh/known_hosts
  script:
    - cp .env.example .env
    - docker-compose up -d
    - sleep 30 # a temporary line to get the logs
    - cat /etc/hosts # debug line
    - docker-compose port pg_db 5432 # debug line
    - netstat -a # debug line
    - docker-compose ps # debug line
    - go test -v -timeout 30s ./... -tags=withDB

  only:
    - merge_request
    - dev
    - master

The logs I get for

variables: 
   PGHOST: localhost
$ cp .env.example .env
$ docker-compose up -d
Recreating alp-logger_pg_db_1 ... 
Recreating alp-logger_pg_db_1 ... done
store-init is up-to-date
$ sleep 30
$ cat /etc/hosts
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.17.0.2	runner-lxzkchpx-project-304-concurrent-0
$ docker-compose port pg_db 5432
0.0.0.0:5432
$ netstat -a
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       
tcp        0      0 runner-lxzkchpx-project-304-concurrent-0:50294 static.124.194.21.65.clients.your-server.de:ssh TIME_WAIT   
Active UNIX domain sockets (servers and established)
Proto RefCnt Flags       Type       State         I-Node Path
$ docker-compose ps
   Name                 Command              State           Ports         
---------------------------------------------------------------------------
pg_db        docker-entrypoint.sh postgres   Up      0.0.0.0:5432->5432/tcp
store-init   ./alp-store                     Up                            

and the error of connecting to postgres db:

failed to connect to `host=localhost user=test database=test`: dial error (dial tcp [::1]:5432: connect: cannot assign requested address)

The logs for debug commands are same, so I'll skip them. The errors I get for

variables: 
    PGHOST: pg_db

and for any other named host like docker.

failed to connect to `host=pg_db user=test database=test`: hostname resolving error (lookup pg_db on 1.1.1.1:53: no such host)

The errors I get for

variables: 
    PGHOST: 127.0.0.1
failed to connect to `host=127.0.0.1 user=test database=test`: dial error (dial tcp 127.0.0.1:5432: connect: connection refused)

答案1

得分: 0

在本地机器上运行容器和在GitLab中使用docker:dind运行容器之间的一个重要区别是,容器不可在'localhost'上访问,而是在docker:dind容器上可用。

如果你想与这个容器通信,在你的场景中,postgres容器将在docker:5432上可用(dockerdocker:dind容器的主机名,你的postgres容器在其中进行端口映射)。

使用简单的HTTP服务容器进行说明

作为一个简化的例子,如果你在本地运行容器strm/helloworld-http并进行端口映射,以下命令可以工作:

docker run -d --rm -p 80:80 strm/helloworld-http
# 给它一些时间启动
curl http://localhost  # 这个可以工作

然而,在GitLab中相同的设置不起作用:

myjob:
  variables:  # 这些变量不一定是必需的
    DOCKER_TLS_CERTDIR: ""
    DOCKER_HOST: "tcp://docker:2375"
  services:
    - docker:dind
  script:
    - docker run -d --rm -p 80:80 strm/helloworld-http
    - sleep 10
    - curl http://localhost  # 失败!

修复的方法是使用docker主机名:

script:
    - docker run -d --rm -p 80:80 strm/helloworld-http
    - sleep 10
    - curl http://docker  # 可以工作!
英文:

One of the important distinctions between running containers on your local machine and running them in GitLab using docker:dind is that the containers are not available on 'localhost' -- they are available on the docker:dind container.

If you want to talk to this container, in your scenario, the postgres container would be available on docker:5432 (docker being the hostname of the docker:dind container where your postgres container has its port mapping).

Illustration with simple HTTP service container

As a simplified example if you were to run the container strm/helloworld-http locally with a port mapping, the following works:

docker run -d --rm -p 80:80 strm/helloworld-http
# give it some time to startup
curl http://localhost  # this works

However, the same setup in GitLab does not:

myjob:
  variables:  # these variables are not necessarily required
    DOCKER_TLS_CERTDIR: ""
    DOCKER_HOST: "tcp://docker:2375"
  services:
    - docker:dind
  script:
    - docker run -d --rm -p 80:80 strm/helloworld-http
    - sleep 10
    - curl http://localhost  # Fails!

One fix would be to use the docker hostname instead:

script:
    - docker run -d --rm -p 80:80 strm/helloworld-http
    - sleep 10
    - curl http://docker  # works!

huangapple
  • 本文由 发表于 2022年3月14日 02:42:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/71459760.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定