Home > database >  Multi-stage Docker build doesn't copy files created from the previous stage
Multi-stage Docker build doesn't copy files created from the previous stage

Time:09-15

I have a Django app whose Docker build is two stages:

  • 1st stage uses a Node image to compile static assets using Gulp. This stage creates the node_modules directory and a folder named build.
  • 2nd stage is supposed to copy files from the previous stage and install the python dependencies.

My problem is that the new folders created by the 1st stage aren't being carried over.

Here's the Dockerfile:

# Dockerfile
# STAGE 1: Compile static assets
# ----------------------------
FROM node:17-slim as client-builder

ARG APP_HOME=/code

WORKDIR ${APP_HOME}

COPY . ${APP_HOME}
# npm's post-install script will use GulpJs to compile the static 
# assets into a folder named "build"
RUN npm install && npm cache clean --force


# STAGE 2: Add python dependencies
# ----------------------------
FROM python:3.10-slim as python-build-stage

ARG APP_HOME=/code
ARG USERNAME=docker

ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
ENV POETRY_NO_INTERACTION 1
ENV POETRY_VIRTUALENVS_CREATE false
ENV POETRY_CACHE_DIR "/var/cache/pypoetry"
ENV POETRY_HOME "/usr/local"

WORKDIR ${APP_HOME}

# Create the user
RUN addgroup --system ${USERNAME} \
    && adduser --system --ingroup ${USERNAME} ${USERNAME}

# Install apt packages
RUN apt-get update && apt-get install --no-install-recommends -y \
  # dependencies for building Python packages
  build-essential \
  # psycopg2 dependencies
  libpq-dev \
  # dev utils
  git zsh

# Copy project files
COPY --from=client-builder --chown=${USERNAME}:${USERNAME} ${APP_HOME} ${APP_HOME}

# Install python dependencies
RUN pip install --upgrade pip
RUN pip install poetry
RUN poetry install --no-interaction --no-ansi

# Set default shell
RUN chsh -s $(which zsh)

# Set user
USER ${USERNAME}

Things I tried

  • The first stage runs correctly. Gulp.js is able to run, so node_modules must have been created correctly. I tried to debug the first stage and saw all files being created correctly.
  • Also tried running as root
  • I also tried to "log" the contents of the workspace with RUN ls . >> /tmp/ls.txt and the contents of the file list surprised me:

I can see the folders being listed there:

enter image description here

But when I ls the actual workspace, I don't see anything:

enter image description here

What is happening?

Docker-compose

I forgot to mention, I'm using docker-compose to build and start these images:

version: '3.10'

services:
  db.postgres:
    image: "postgres"
    env_file: .env
    volumes:
      - postgres_data:/var/lib/postgresql/data/
    ports:
      - 5432:5432
  web:
    build: .
    command: >
      zsh -c "python3 /code/manage.py migrate &&
              python3 /code/manage.py runserver 0.0.0.0:8000"
    env_file: .env
    volumes:
      - .:/code
    ports:
      - 8000:8000
    depends_on:
      - db.postgres
    restart: on-failure:5

volumes:
  postgres_data:

CodePudding user response:

The problem here is that during the build process you're installing things into the /code directory:

ARG APP_HOME=/code
...
COPY --from=client-builder --chown=${USERNAME}:${USERNAME} \
  ${APP_HOME} ${APP_HOME}

But in your docker-compose.yaml, you're masking the /code directory by mounting your local directory on top of it:

  web:
    ...
    volumes:
      - .:/code

That means anything placed there during the build process will be hidden.

One solution is to mount your local directory somewhere other than /code (and then update your code/config/whatever to be aware of the new mountpoint).

  • Related