自定义docker镜像没有运行postgres

时间:2017-04-03 04:07:14

标签: node.js postgresql docker circleci

我正在尝试为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;"

另见:

感谢

1 个答案:

答案 0 :(得分:2)

问题

问题是您没有定义图像应该运行的命令,因此它默认为在Ubuntu基本映像中设置的命令:/bin/bash

查看CMD的文档:

  

注意:请勿将RUNCMD混淆。 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。
  • 等待Postgres接受连接(即脚本现在所做的事情)。
  • 运行psql命令以创建数据库。
  • 使用exec $@结束脚本以执行Docker CMD

设置起来有点容易,但不适合制作。