3

For testing, I'm trying to setup Postgres inside of a docker container so that our python app can run it's test suite against it.

Here's my Dockerfile:

# Set the base image to Ubuntu
FROM ubuntu:16.04

# Update the default application repository sources list
RUN apt-get update && apt-get install -y \
  python2.7 \
  python-pip \
  python-dev \
  build-essential \
  libpq-dev \
  libsasl2-dev \
  libffi-dev \
  postgresql

USER postgres
RUN /etc/init.d/postgresql start && \
  psql -c "CREATE USER circle WITH SUPERUSER PASSWORD 'circle';" && \
  createdb -O darwin circle_test
USER root
RUN service postgresql stop && service postgresql start

# Upgrade pip
RUN pip install --upgrade pip

COPY . /app
WORKDIR /app

RUN pip install -r requirements.txt

EXPOSE 5000

# Set the container entrypoint
ENTRYPOINT ["gunicorn", "--config", "/app/config/gunicorn.py", "--access-logfile", "-", "--error-logfile", "-", "app:app"]

When I run:

docker run --entrypoint python darwin:latest -m unittest discover -v -s test

I'm getting:

could not connect to server: Connection refused
        Is the server running on host "localhost" (127.0.0.1) and accepting
        TCP/IP connections on port 5432?

The only way I can get it to work is if I ssh into the container, restart postgres and run the test suite directly.

Is there something I'm missing here?

doremi
  • 14,921
  • 30
  • 93
  • 148
  • 1
    your `RUN service postgresql stop && service postgresql start` is in a RUN, not in a CMD or ENTRYPOINT, so it is "forgotten" when the container starts – user2915097 Apr 19 '17 at 18:03
  • have a look at the reference PostgreSQL Dockerfile at https://github.com/docker-library/postgres/blob/3d4e5e9f64124b72aa80f80e2635aff0545988c6/9.6/Dockerfile – user2915097 Apr 19 '17 at 18:09
  • I changed `RUN` to `CMD` but it still exhibits the same error. – doremi Apr 19 '17 at 18:17
  • you can have only one CMD in a Dockerfile, the latest is used, see the links in my answer, and the supervisor one – user2915097 Apr 19 '17 at 18:19

1 Answers1

2

In a Dockerfile you have

  • a configuration phase, the RUN directive (and some others)

  • the process(es) you start, that you put in either

CMD

or

ENTRYPOINT

see the docs

https://docs.docker.com/engine/reference/builder/#cmd

and

https://docs.docker.com/engine/reference/builder/#entrypoint

when a container has completed what it has to do in this start phase, it dies.

This is why the reference Dockerfile for PostgreSQL, at

https://github.com/docker-library/postgres/blob/3d4e5e9f64124b72aa80f80e2635aff0545988c6/9.6/Dockerfile

ends with

CMD ["postgres"]

if you want to start several processes, see supervisord or such tool (s6, daemontools...)

https://docs.docker.com/engine/admin/using_supervisord/

user2915097
  • 30,758
  • 6
  • 57
  • 59
  • That makes a lot of sense. Could I exchange my final `ENTRYPOINT` with a bash script that both starts PG and gunicorn? – doremi Apr 19 '17 at 18:25
  • yes that is an option, read http://stackoverflow.com/questions/21553353/what-is-the-difference-between-cmd-and-entrypoint-in-a-dockerfile you can see the entrypoint as a verb, the CMD as an argument, see https://hub.docker.com/r/k3ck3c/nethogs/ if you just run it, it starts monitoring the wlan0 device, if you add wlp2s0 (or eth1 or any) at the end of you `docker run...` it monitors wlp2s0 (or eth1 or any) – user2915097 Apr 19 '17 at 18:52