我正在尝试为circleci v2创建自己的自定义docker文件。但是,我遇到了postgres服务器没有运行的问题。我已经service postgresql start
无法使用。
我得到的信息是:
psql: could not connect to server: Connection refused
Is the server running locally and accepting
connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?
Dockerfile:
FROM ubuntu:16.04
ENV NODEJS_VERSION 6
ENV POSTGRESQL_VERSION 9.6
RUN apt-get update && apt-get -y install curl
RUN curl -sL https://deb.nodesource.com/setup_$NODEJS_VERSION.x | bash -
RUN apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys B97B0AFCAA1A47F044F244A07FCC7D46ACCC4CF8
RUN echo "deb http://apt.postgresql.org/pub/repos/apt/ precise-pgdg main" > /etc/apt/sources.list.d/pgdg.list
RUN apt-get update
RUN apt-get install -y \
nodejs \
make \
git \
g++ \
python-software-properties \
software-properties-common \
postgresql-$POSTGRESQL_VERSION \
postgresql-client-$POSTGRESQL_VERSION \
postgresql-contrib-$POSTGRESQL_VERSION
RUN echo "host all all 0.0.0.0/0 md5" >> /etc/postgresql/$POSTGRESQL_VERSION/main/pg_hba.conf
RUN echo "listen_addresses='*'" >> /etc/postgresql/$POSTGRESQL_VERSION/main/postgresql.conf
USER postgres
RUN service postgresql start && \
psql -c "create database pgdb;" && \
psql -c "create role pgrole with login password 'pgrole'; grant all privileges on database pgdb to pgrole;"
另见:
感谢
答案 0 :(得分:2)
问题是您没有定义图像应该运行的命令,因此它默认为在Ubuntu基本映像中设置的命令:/bin/bash
。
查看CMD的文档:
注意:请勿将
RUN
与CMD
混淆。RUN
实际运行命令并提交结果;CMD
在构建时不执行任何操作,但指定了图像的预期命令。
因此,您的RUN service postgresql start
在构建时间执行,并且该命令的结果将作为图层提交给图像。当您启动图像时,例如在CircleCI上,执行图像的CMD
。由于您没有设置它,它使用Ubuntu指定的那个:/bin/bash
。这意味着在运行时,事实上Postgres正在运行。
要记住的另一件事是CMD
不能是守护进程。只要在前台执行进程,Docker就会保持容器运行,因此如果执行CMD service postgresql start
,Docker将在命令返回后退出容器。
我建议您重做整个CI设置。如果你在CMD
中启动Postgres,则无法覆盖该命令来运行测试(或者Postgres不会再次运行)。
相反,使用两个图像,一个用于您的应用,一个用于Postgres。你启动Postgres,等待它接受连接,然后在你的app
容器中运行测试。
您可以重复使用现有的postgresql
图像,该图像会在您启动时为您创建数据库和用户。您需要添加一个脚本以等待数据库准备就绪,或者您的测试将在数据库接受连接之前运行。请参阅此帖子:https://discuss.circleci.com/t/waiting-for-database/10946
使用这种方法,可以更容易地同时运行多个服务,并且仍然可以完全自由地在Circle CI上运行哪些命令。
稍微容易一些,但仅仅是为了测试,是创建一个启动Postgres的入口点并等待它准备就绪的选项。创建一个脚本,将其复制到Dockerfile
并将ENTRYPOINT
指向它。在脚本中,运行services postgresql start
,创建数据库,然后等待Postgres接受连接。完成后,使用exec $@
执行传递给容器的任何命令。
您可以在此处找到我们用于等待Postgres的脚本:https://gist.github.com/jdno/09377bde65095773e5daf1aaa8e62ef4
此脚本可以轻松扩展为ENTRYPOINT
。
services postgresql start
启动Postgres。psql
命令以创建数据库。exec $@
结束脚本以执行Docker CMD
。设置起来有点容易,但不适合制作。