I have an Express.js application that takes input from the terminal and outputs data to the terminal interactively. For data storage, I am using PostgreSQL. The application needs to run interactively and should only start after the PostgreSQL container is properly running. I am using Docker Compose to manage the containers.
However, I am facing issues with the order of running containers. It seems like the Express.js app container is trying to start before the PostgreSQL container is ready, causing connection errors. Or it doesn’t work interactively.
How can I configure my docker-compose.yml file to ensure that the Express.js application waits for the PostgreSQL container to be fully operational before starting and it works interactively on terminal?
here is my docker-compose.yml file:
services:
postgresdb:
image: "postgres:latest"
environment:
- POSTGRES_USER=root
- POSTGRES_PASSWORD=root
- POSTGRES_DB=userinfo
container_name: postgresqldb
healthcheck:
test: ["CMD", "pg_isready", "-U", "root", "-d", "userinfo"]
interval: 10s
timeout: 10s
retries: 3
app:
build: .
depends_on:
postgresdb:
condition: service_healthy
stdin_open: true
tty: true
My Dockerfile:
FROM node:20
WORKDIR /myapp
COPY . .
RUN npm install
EXPOSE 3000
CMD [ "npm", "start" ]
If you think the code needs to be written in this question I will also add the code.
AFTER EDIT:
Now, it runs well. but it gets stuck here after I input 1
:
[+] Running 3/3
✔ Network bind-mounts_default Created 0.0s
✔ Container postgresqldb Created 0.0s
✔ Container bind-mounts-app-1 Created 0.0s
Attaching to bind-mounts-app-1, postgresqldb
postgresqldb | The files belonging to this database system will be owned by user "postgres".
postgresqldb | This user must also own the server process.
postgresqldb |
postgresqldb | The database cluster will be initialized with locale "en_US.utf8".
postgresqldb | The default database encoding has accordingly been set to "UTF8".
postgresqldb | The default text search configuration will be set to "english".
postgresqldb |
postgresqldb | Data page checksums are disabled.
postgresqldb |
postgresqldb | fixing permissions on existing directory /var/lib/postgresql/data ... ok
postgresqldb | creating subdirectories ... ok
postgresqldb | selecting dynamic shared memory implementation ... posix
postgresqldb | selecting default max_connections ... 100
postgresqldb | selecting default shared_buffers ... 128MB
postgresqldb | selecting default time zone ... Etc/UTC
postgresqldb | creating configuration files ... ok
postgresqldb | running bootstrap script ... ok
postgresqldb | performing post-bootstrap initialization ... ok
postgresqldb | initdb: warning: enabling "trust" authentication for local connections
postgresqldb | initdb: hint: You can change this by editing pg_hba.conf or using the option -A, or --auth-local and --auth-host, the next time you run initdb.
postgresqldb | syncing data to disk ... ok
postgresqldb |
postgresqldb |
postgresqldb | Success. You can now start the database server using:
postgresqldb |
postgresqldb | pg_ctl -D /var/lib/postgresql/data -l logfile start
postgresqldb |
postgresqldb | waiting for server to start....2024-08-01 14:14:30.694 UTC [48] LOG: starting PostgreSQL 16.3 (Debian 16.3-1.pgdg120+1) on aarch64-unknown-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
postgresqldb | 2024-08-01 14:14:30.694 UTC [48] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
postgresqldb | 2024-08-01 14:14:30.696 UTC [51] LOG: database system was shut down at 2024-08-01 14:14:30 UTC
postgresqldb | 2024-08-01 14:14:30.699 UTC [48] LOG: database system is ready to accept connections
postgresqldb | done
postgresqldb | server started
postgresqldb | CREATE DATABASE
postgresqldb |
postgresqldb |
postgresqldb | /usr/local/bin/docker-entrypoint.sh: ignoring /docker-entrypoint-initdb.d/*
postgresqldb |
postgresqldb | waiting for server to shut down...2024-08-01 14:14:30.851 UTC [48] LOG: received fast shutdown request
postgresqldb | .2024-08-01 14:14:30.853 UTC [48] LOG: aborting any active transactions
postgresqldb | 2024-08-01 14:14:30.855 UTC [48] LOG: background worker "logical replication launcher" (PID 54) exited with exit code 1
postgresqldb | 2024-08-01 14:14:30.855 UTC [49] LOG: shutting down
postgresqldb | 2024-08-01 14:14:30.855 UTC [49] LOG: checkpoint starting: shutdown immediate
postgresqldb | 2024-08-01 14:14:30.881 UTC [49] LOG: checkpoint complete: wrote 922 buffers (5.6%); 0 WAL file(s) added, 0 removed, 0 recycled; write=0.011 s, sync=0.014 s, total=0.026 s; sync files=301, longest=0.004 s, average=0.001 s; distance=4255 kB, estimate=4255 kB; lsn=0/1911FA0, redo lsn=0/1911FA0
postgresqldb | 2024-08-01 14:14:30.886 UTC [48] LOG: database system is shut down
postgresqldb | done
postgresqldb | server stopped
postgresqldb |
postgresqldb | PostgreSQL init process complete; ready for start up.
postgresqldb |
postgresqldb | 2024-08-01 14:14:30.968 UTC [1] LOG: starting PostgreSQL 16.3 (Debian 16.3-1.pgdg120+1) on aarch64-unknown-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
postgresqldb | 2024-08-01 14:14:30.969 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432
postgresqldb | 2024-08-01 14:14:30.969 UTC [1] LOG: listening on IPv6 address "::", port 5432
postgresqldb | 2024-08-01 14:14:30.970 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
postgresqldb | 2024-08-01 14:14:30.973 UTC [64] LOG: database system was shut down at 2024-08-01 14:14:30 UTC
postgresqldb | 2024-08-01 14:14:30.976 UTC [1] LOG: database system is ready to accept connections
bind-mounts-app-1 |
bind-mounts-app-1 | > [email protected] start
bind-mounts-app-1 | > node app.js
bind-mounts-app-1 |
bind-mounts-app-1 | Choose an option:
bind-mounts-app-1 | 1. Add a name to the DB
bind-mounts-app-1 | 2. Get all names from the DB
bind-mounts-app-1 | 3. Quit
bind-mounts-app-1 |
Enter your choice: Server is running on http://localhost:3000
1
postgresqldb | 2024-08-01 14:19:31.073 UTC [62] LOG: checkpoint starting: time
postgresqldb | 2024-08-01 14:19:35.393 UTC [62] LOG: checkpoint complete: wrote 45 buffers (0.3%); 0 WAL file(s) added, 0 removed, 0 recycled; write=4.306 s, sync=0.006 s, total=4.320 s; sync files=12, longest=0.005 s, average=0.001 s; distance=261 kB, estimate=261 kB; lsn=0/19533D8, redo lsn=0/19533A0
You have set the dependency on the postgres container as service_completed_successfully
, but postgres never “completes” (it is a persistent service). You should be using the service_healthy
dependency instead:
services:
postgresdb:
image: "postgres:latest"
environment:
- POSTGRES_USER=root
- POSTGRES_PASSWORD=root
- POSTGRES_DB=userinfo
container_name: postgresqldb
healthcheck:
test: ["CMD-SHELL", "pg_isready -U root -d userinfo"]
timeout: 20s
retries: 10
app:
build: .
depends_on:
postgresdb:
condition: service_healthy
stdin_open: true
tty: true
See “Control startup and shutdown order in Compose”” for complete documentation.
You probably want to tune your healthcheck a bit; the interval
value defaults to 30 seconds so you’ll have to wait at least that long for the container to become healthy. Also, prefer CMD
over CMD-SHELL
unless you have a specific need to run a shell script. Something like this is perhaps more reasonable:
services:
postgresdb:
image: "postgres:latest"
environment:
- POSTGRES_USER=root
- POSTGRES_PASSWORD=root
- POSTGRES_DB=userinfo
container_name: postgresqldb
healthcheck:
test: ["CMD", "pg_isready", "-U", "root", "-d", "userinfo"]
interval: 10s
timeout: 10s
retries: 3
app:
build: .
depends_on:
postgresdb:
condition: service_healthy
stdin_open: true
tty: true