I want to run a yesod web application in one docker container, linked to a postgres database in another docker container.
I have the following file hierarchy:
/
api/
Dockerfile
database/
Dockerfile
docker-compose.yml
The docker-compose.yml
looks like this:
database:
build: database
api:
build: api
command: .cabal/bin/yesod devel # dev setting
environment:
- HOST=0.0.0.0
- PGHOST=database
- PGPORT=5432
- PGUSER=postgres
- PGPASS
- PGDATABASE=postgres
links:
- database
volumes:
- api:/home/haskell/
ports:
- "3000:3000"
Running sudo docker-compose up
fails either to start the api container at all or, just as often, with the following error:
api_1 | Yesod devel server. Press ENTER to quit
api_1 | yesod: <stdin>: hGetLine: end of file
personal_api_1 exited with code 1
If, however, I run sudo docker-compose database up &
then start up the api container without using compose but instead using
sudo docker run -p 3000:3000 -itv /home/me/projects/personal/api/:/home/haskell --link personal_database_1:database personal_api /bin/bash
I can export
the environment variables being set up in the docker-compose.yml
file then manually run yesod devel
and visit my site successfully on localhost.
Finally, I obtain a third different behaviour if I run sudo docker-compose run api
on its own. This seems to start successfully but I can't access the page in my browser. By running sudo docker-compose run api /bin/bash
I've been able to explore this container and I can confirm the environment variables being set in docker-compose.yml
are all set correctly.
I would like to get the result I achieve from running the database in the background then manually setting the environment in the api container's shell simply by running sudo docker-compose up
.
Clearly the three different approaches I'm trying do slightly different things. But from my understanding of docker and docker-compose I would expect them to be essentially equivalent. Please could someone explain how and why they differ and, if possible, how I might achieve my desired result?
The error-message suggests the API container is expecting input from the command-line, which expects a TTY to be present in your container.
In your "manual" start, you tell docker to create a TTY in the container via the -t
flag (-itv
is shorthand for -i -t -v
), so the API container runs successfully.
To achieve the same in docker-compose, you'll have to add a tty
key to the API service in your docker-compose.yml
and set it to true
;
database:
build: database
api:
build: api
tty: true # <--- enable TTY for this service
command: .cabal/bin/yesod devel # dev setting