JulienCorb
ERROR 42P01 (undefined_table) relation "myrelation" does not exist
I am creating a Docker container for my umbrella app that so far contains just one phoenix API app.
This application has simply one DB table that is made of political parties, called “parties”.
when I run docker-compose up and visit http://localhost:4001/api/v1/parties I get the following error: ERROR 42P01 (undefined_table) relation "parties" does not exist
Obviously my table does not exists. However I do run my migrations in my Dockerfile:
# ./Dockerfile
# Elixir base image to start with
FROM elixir:1.8
# install hex package manager
RUN mix local.hex --force
RUN mix local.rebar --force
# install the latest Phoenix
RUN mix archive.install https://github.com/phoenixframework/archives/raw/master/phoenix_new.ez --force
# install NodeJS and NPM
RUN curl -sL https://deb.nodesource.com/setup_10.x -o nodesource_setup.sh
RUN bash nodesource_setup.sh
RUN apt-get install nodejs
RUN apt-get install -y inotify-tools
# create our app folder and copy our code in it and set it as default
RUN mkdir /app
COPY . /app
WORKDIR /app
# install dependencies
RUN mix deps.get
RUN mix deps.compile
# We can't separate the command as each command create a temporary container
# and each container as it own temporary variables
# run migrations
CMD mix ecto.migrate
# run phoenix server. The CMD is run each time the container is launched.
CMD mix phx.server
and here is my docker-compose.yml :
# the version of docker compose we use
version: '2'
services:
# the first container will be called postgres
postgres:
# the image is the last official postgres image
image: postgres
# the volumes allow us to have a shared space between our computer and the docker vm
volumes:
- "./.data/postgres:/var/lib/postgresql"
# set up environment variable for the postgres instance
environment:
POSTGRES_USER: ${PSQL_USER}
POSTGRES_PASSWORD: ${PSQL_PWD}
POOL: 100
# the port to listen
ports:
- "5432:5432"
# the second container is called redis
redis:
# the image is the last official redis image of the version 5
image: redis:5
ports:
- "6379:6379"
volumes:
- ./.data/redis:/var/lib/redis
# set up environment variable for the redis instance
environment:
REDIS_PASSWORD: ${REDIS_PWD}
# our last container is called elixir
elixir:
# build use a path to a Dockerfile
build: .
# we set multiple ports as each of our application (but database) will use a different port
ports:
- "4001:4001"
- "4101:4101"
# we share the entire app with the container, but the libs
volumes:
- ".:/app"
- "/app/deps"
- "/app/apps/admin/assets/node_modules"
# the container will not start if the postgres container isn't running
depends_on:
- postgres
# set up environment variable for the phoenix instance
environment:
POSTGRES_USER: ${PSQL_USER}
POSTGRES_PASSWORD: ${PSQL_PWD}
POSTGRES_DB_TEST: ${PSQL_DB_TEST}
POSTGRES_DB_DEV: ${PSQL_DB}
POSTGRES_HOST: ${PSQL_HOST}
What is wrong with my code ?
Marked As Solved
NobbZ
No, use the hostname postgres to connect to the database rather than an IP that you’ll never know if it will be correct after the next restart of the database.
Never rely on IPs inside of your composed network, only ever use the service names, docker provides a DNS under the hood that will let them resolve properly.
Also Liked
NobbZ
Entrypoint in this context, is what docker runs as ENTRYPOINT. You are using CMD though.
I never really got the difference of these 2, but started to use ENTRYPOINT only, about 2 years back, and never had any issues because of this.
Basically, you need to run a script which as CMD or ENTRYPOINT that creates your DB if it did not exist yet, then runs your migrations and only then starts the application.
Usually a shell script like this is used:
#!/usr/bin/env sh
set -ex # prints each command and fails the script on first error
mix ecto.create || echo "Could not create database, assume it exist already"
mix ecto.migrate
exec mix phx.server
Put this as entrypoint.sh in your project, and chmod +x it. Make sure its in your container and then use ENTRYPOINT entrypoint.sh instead of CMD.
NobbZ
I just realise, you are using two CMD, this is not allowed, only the last CMD specified will be used, it overwrites any previous set CMD.
On my first read I saw this as a RUN.
NobbZ
Try using /app/entrypoint.sh just to be sure.







