I am developing a Node.js app that uses Postgres as its database. I write a "docker-compose.yml" file for Node.js & Postgres.
I create pgdata directory, Then I write my Dockerfile to build Node.js image:
FROM node:14.15.0
WORKDIR "/usr/src/app"
CMD [ "npm", "start" ]
And this is how I write my "docker-compose.yml" file:
version: "3.7"
services:
db:
image: postgres:13
env_file:
- ./.env.postgres
volumes:
- type: bind
source: ./pgdata
target: /var/lib/postgresql/data
volume:
nocopy: true
environment:
PGDATA: /var/lib/postgresql/data/pgdata
container_name: ${APP_NAME}-db
express-app:
image: ${APP_NAME}-express-app:1
build:
context: .
dockerfile: ./Dockerfile
volumes:
- type: bind
source: .
target: /usr/src/app
volume:
nocopy: true
env_file:
- ./.env
- ./.env.postgres
depends_on:
- db
ports:
- "${APP_PORT}:${DOCKER_CONTAINER_APP_PORT}"
environment:
POSTGRES_HOST: db
And then I start my app by running this command: docker-compose up --build
and everything was OK. docker build image and create its containers. My app works fine but when I remove its image (node.js image, for some reasons), and run the docker-compose up --build
command it throws this error for me:
Building with native build. Learn about native build in Compose here: https://docs.docker.com/go/compose-native-build/
Building express-app
error checking context: 'can't stat '/home/project1/pgdata/pgdata''.
ERROR: Service 'express-app' failed to build
And after that, I realize that docker create a directory inside the mounted directory (pgdata)
So I check it permission with 'ls -ltrha' and this is the output:
total 12K
drwxr-xr-x 3 mjb mjb 4.0K FEB 20 12:34 .
drwx------ 19 systemd-coredump root 4.0K FEB 20 12:34 pgdata
drwxr-xr-x 6 mjb mjb 4.0K FEB 21 12:19 ..
When you build a Docker image, the context directory you give (typically the current directory) is sent to the Docker daemon to build. The goal of this is to be able to COPY
files from the context directory into the Docker image, so you can have a self-contained image that can run without separately needing the application code mounted in.
In your setup, the database content is stored in ./pgdata
, so a subdirectory of the directory you're using as a build context. The data in that directory will be owned by the user in the database container, which frequently won't be the same user as the host user (and that's okay). But now since a different user owns the ./pgdata
directory, the image build sequence can't send the build context directory to the Docker daemon, hence the error you get.
You can create a .dockerignore
file to tell Docker to exclude the database data from the image build (you will never want this in your image no matter what). Put this in the same directory as the Dockerfile
and docker-compose.yml
file. It can contain just
# .dockerignore
# Do not copy host's node_modules into the image; we will RUN npm install
node_modules
# Do not copy database storage into the image at all
pgdata