Dockerfile is copying files from outside of parent directory - docker

I have a simple Dockerfile that is in a directory called /App when I build my docker container using a docker-compose yaml file the dockerfile copies files from one level up, outside the /App folder into the container.
Here is my dockerfile
FROM python:3.8
ENV PYTHONUNBUFFERED 1
WORKDIR /code
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
and here is my docker-compose file
version: '3'
services:
dash:
build:
context: ./App
dockerfile: Dockerfile.dash
container_name: dash_dash
command: ls
volumes:
- .:/code
ports:
- "80:8080"
When I build and run the container the ls command shows that it copied the directory one level above the /App directory, such that the /App directory is included but is not the main directory.

The volumes section of your docker-compose.yml is overriding the working directory:
volumes:
- .:/code
is copying the whole folder where the docker-compose.yml is (so it is copying the /App folder entirely). As a result, your files in your working directory (/code) are overridden.
You should remove the volumes section of your docker-compose.yml. The ls command will then show the contents of the App directory, copied by the COPY . . section of your Dockerfile.

Related

Dockerfile permission for volume

FROM --platform=$BUILDPLATFORM maven:3.8.5-eclipse-temurin-17 AS builder
WORKDIR /server
COPY pom.xml /server/pom.xml
RUN mvn dependency:go-offline
COPY src /server/src
RUN mvn install
# install Docker tools (cli, buildx, compose)
COPY --from=gloursdocker/docker / /
CMD ["mvn", "spring-boot:run"]
FROM builder as prepare-production
RUN mkdir -p target/dependency
WORKDIR /server/target/dependency
RUN jar -xf ../*.jar
FROM eclipse-temurin:17-jre-focal
EXPOSE 8080
VOLUME /app
ARG DEPENDENCY=/server/target/dependency
COPY --from=prepare-production ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY --from=prepare-production ${DEPENDENCY}/META-INF /app/META-INF
COPY --from=prepare-production ${DEPENDENCY}/BOOT-INF/classes /app
ENTRYPOINT ["java","-cp","app:app/lib/*","com.server.backend.BackendApplicaiton"]
and I need to save the files in /app to the /opt/containers/backend directory (absolute). Code bellow is my docker compose file.
version: "3.9"
services:
backend:
container_name: "backend"
build: backend
environment:
- ${MSSQL_PASSWORD}
ports:
- 3000:8080
volumes:
- /opt/containers/backend:/app
networks:
- backend
networks:
backend:
name: backend
driver: bridge
internal: false
if I run this and create volume in docker, everything works, files are saved inside docker volume, but when I set absolute path as in the docker compose file, directory is empty and app does not run. I am sure the error is in permissions, but I cant figured it out where and I could not find any solutions :(
Thank you for all your replies and help.

How to use GCP service account json files in Docker

I am dockerizing Fastapi application which is using Firebase. I need to access service json file and I have configured my docker container as follows.
Dockerfile
FROM python:3.10-slim
ENV PYTHONUNBUFFERED 1
WORKDIR /app
# Install dependencies
COPY ./requirements.txt /requirements.txt
EXPOSE 8000
RUN pip install --no-cache-dir --upgrade -r /requirements.txt
RUN mkdir /env
# Setup directory structure
COPY ./app /app/app
COPY ./service_account.json /env
CMD ["uvicorn", "app.app:app", "--host", "0.0.0.0", "--port", "8000"]
Docker-compose file
version: "3.9"
services:
app:
build:
context: .
restart: always
environment:
- GOOGLE_APPLICATION_CREDENTIALS_CLOUDAPI=${GOOGLE_APPLICATION_CREDENTIALS_CLOUDAPI}
- GOOGLE_APPLICATION_CREDENTIALS=${GOOGLE_APPLICATION_CREDENTIALS}
volumes:
- ./env:/env
volumes:
env:
Now when I run docker-compose up -d --build the container fails with the error FileNotFoundError: [Errno 2] No such file or directory: '/env/service_account.json'. When I inspect the container I can see the ENV variable set successfully as shown "GOOGLE_APPLICATION_CREDENTIALS=/env/service_account.json",. Now why is this failing?
You have context: . and COPY ./service_account.json /env
But when you run the container, you have
volumes:
- ./env:/env
Meaning your service_acccount file is not in ./env folder, and is instead outside of it.
When you mount a volume, it replaces the directory inside the container, so if you need a local env folder mounted as /env in the container, then you should move your JSON file somewhere else such as /opt (COPY ./service_account.json /opt), and then set GOOGLE_APPLICATION_CREDENTIALS=/opt/service_account.json
If you don't need the whole folder, then you only need
volumes:
- ./service_account.json:/env/service_account.json:ro
Otherwise, move the JSON file into ./env on your host and change COPY ./env/service_account.json /env

Docker: Shared volume when build

I have this files:
docker-compose.yml (shortened):
version: '3.7'
services:
php-fpm:
build:
context: .
dockerfile: docker/php/Dockerfile
target: dev
volumes:
- .:/app
frontend:
build:
context: .
dockerfile: docker/php/Dockerfile
target: frontend
volumes:
- .:/app
docker/php/Dockerfile (shortened):
FROM alpine:3.13 AS frontend
WORKDIR /app
COPY . .
RUN apk add npm
RUN npm install
RUN npx webpack -p --color --progress
FROM php:7.4-fpm AS dev
ENTRYPOINT ["docker-php-entrypoint"]
WORKDIR /app
COPY ./docker/php/www-dev.conf /usr/local/etc/php-fpm.d/www.conf
CMD ["php-fpm"]
I want to use all what building in frontend (as I understood at the stage build at this time volumes are not available) in php-fpm container, but I get something like this: file_get_contents(/app/static/frontend.version): failed to open stream.
How I can do this? I don't understand very well in Docker and the only solution I have is to move build script to php-fpm container.
You need to delete the volumes: in your docker-compose.yml file. They replace the entire contents of the image's /app directory with content from the host, which means everything that gets done in the Dockerfile gets completely ignored.
The Dockerfile you show uses a setup called a multi-stage build. The important thing you can do with this is build the first part of your image using Node, then COPY --from=frontend the static files into the second part. You do not need to declare a second container in docker-compose.yml to run the first stage, the build sequence runs this automatically. This at a minimum looks like
COPY --from=frontend /app/build ./static
You will also need to COPY the rest of your application code into the image.
If you move the Dockerfile up to the top of your project's source tree, then the docker-compose.yml file becomes as simple as
version: '3.8'
services:
php-fpm:
build: . # default Dockerfile, default target (last stage)
# do not overwrite application code with volumes:
# no separate frontend: container
But you've put a little bit more logic in the Dockerfile. I might write:
FROM node:lts AS frontend # use a prebuilt Node image
WORKDIR /app
COPY package*.json . # install dependencies first to save time on rebuild
RUN npm install
COPY . . # (or a more specific subdirectory?)
RUN npx webpack -p --color --progress
FROM php:7.4-fpm AS dev
WORKDIR /app
COPY . . # (or a more specific subdirectory?)
COPY --from=frontend /app/build ./static
COPY ./docker/php/www-dev.conf /usr/local/etc/php-fpm.d/www.conf
# don't need to repeat unmodified ENTRYPOINT/CMD from base image

Docker compose is failing when copying npmrc

I am getting this error when trying to run my docker with docker compose
=> ERROR [6/9] COPY .npmrc .npmrc
0.0s => ERROR [7/9] ADD package.json /Users/gs/Documents/Dev/DockerDi 0.0s
version: "3"
services:
gs-service:
build:
context: .
dockerfile: ./gs/Dockerfile
ports:
- 8081:8081
ui-service:
build:
context: .
dockerfile: ./ui/Dockerfile
ports:
- 8083:8083
Here is the detail of the Dockerfile which is failing. This is a subdirectory. For example /user/gs/dockerexperiment/ui
docker-compose file is in parent directory. For example
/user/gs/dockerexperiment
Dockerfile is in subdirectory. For example
/user/gs/dockerexperiment/ui
I know something is going wrong with the class path but I am having a difficult time figuring out what I am missing
A Dockerfile operates on a build context; this is a copy of the directory tree you name as the build: { context: } in the docker-compose.yml file (or, if you're using docker build directly, its directory argument).
build:
context: .
In the Dockerfile, any COPY (or ADD) instructions are interpreted as relative to this directory tree. (If it looks like an absolute path, it's still relative to this directory; any .. path steps that would step outside this directory get ignored.)
COPY package*.json ./
# copies ./package.json, relative to the context directory
But, you clarify in a comment, this isn't actually where your files are. Relative to the docker-compose.yml file, you need ./ui/package.json; the Dockerfile is also in the same subdirectory.
The Dockerfile you show doesn't seem to need any content from outside its immediate tree, so the easiest way to address this is to set the ui directory as the build context:
version: '3.8'
services:
ui:
build: ./ui
# Same as
# build:
# context: ./ui
# dockerfile: Dockerfile # relative to the context directory
ports:
- 8085:8085
In the Dockerfile, you can remove the duplicate ADD package.json line, and you should remove the dangerous RUN npm set config line. You can also set a much shorter WORKDIR, something like /app would be typical.
If you don't want to change the docker-compose.yml file, the other possible change is to adjust the Dockerfile so that its COPY paths are relative to the (parent) build-context directory.
COPY ui/package*.json .
The advantage of doing this is that you can access files from the other application, if you need to, or you can store shared files in that parent directory.
FROM node:14
# Add the public TLS key for our internal repository
# (from the parent directory)
COPY repository.example.com.crt /usr/local/share/ca-certificates
RUN update-ca-certificates
WORKDIR /app
# Also get our local npm configuration (from the parent directory)
COPY .npmrc .
# Install the ./ui application
COPY ui/package*.json .
RUN npm ci
COPY ui/src ./src
EXPOSE 8085
CMD ["npm", "start"]

Docker-compose: node_modules mouting as volume

I have an app with the following services:
cockpit/ - use as a headless CMS service.
frontend/ - bootstrapped by Create React App.
I have a question about frontend
frontend/Dockerfile
FROM node:12.16.3-alpine
RUN mkdir -p /app
WORKDIR /app
COPY package.json yarn.lock /app/
RUN yarn install --pure-lockfile
COPY . /app
CMD ["yarn", "run", "start"]
docker-compose.yml
frontend:
...
volumes:
- ./frontend:/app
- /app/node_modules
The question is /app/node_modules is same meaning with ./frontend/node_modules:/app/node_modules ?
If not, what is the difference?
/app/node_modules creates a directory inside the container and the Docker Engine automatically creates an anonymous volume for this (i.e. it should will probably be empty). This is from the docs about the compose file spec in the "Short Syntax" section.
./frontend/node_modules:/app/node_modules creates a bind mount. The ./frontend/node_modules directory from your host machine will be shared with the container.
In response to followups regarding why using /app/node_modules works but the other syntax does not:
Your yarn install command creates a node_modules folder inside the Docker image. This created folder conflicts with the existing frontend/node_modules folder you have locally when trying to run with ./frontend/node_modules:/app/node_modules. When you specify /app/node_modules, the container uses the directory created during the build step.

Resources