英文:
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
上可用(docker
是docker: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!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论