dockerdockerfilecontainers

run command after mounting volumes


Im trying to build a container image that will download a git repo and move it to a specific location in a container. I am successfully able to build the image and downloading the repo but the coping of the file is failing and i am not getting any error. The location the file is to be copied to is a mounted volume from the host so what i assume what is happening is the directory is not there when it is trying to copy it so its failing. I am using Dockerfile to create the image but the files never seem to be copied but the repo is downloaded.

I have attempt to use the CMD to copy the script but same result and also tried using a script with the copy command that starts with a sleep timer of 10 seconds but the files are never copied.

The container does have read/write to the mount as the app is updating the config in the mount.

Here is the contents of my Dockerfile

FROM ubuntu:22.04
RUN apt-get -y install git && git clone "https://github.com/user/repo.git" 
RUN cp /repo/file.py /config/webapp/cleanup_script/
RUN pip3 install x, y, z 
# keeping the container running.
CMD sleep infinity

Any idea what i am doing wrong here?

docker-compose file.

services:
  webapp:
    image: 0594dd495719
    domainname: webapp.serbio
    container_name: webapp
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Europe/London
      - UMASK_SET=000
      - WEBUI_PORT=8080
    volumes:
      - /configs/webapp:/config/
      - /mnt:/mnt/
    ports:
      - 6881:6881
      - 6881:6881/udp
      - 8080:8080
      - 51111:51111
      - 51111:51111/udp
    networks:
       vpcbr:
        ipv4_address: 10.1.1.10
    restart: unless-stopped

This image will be run in docker and in kubernetes.


Solution

  • The Dockerfile runs before any volumes are created or mounted. In the Dockerfile you can't change volume content, this needs to happen when the container starts.

    The usual pattern I use here is an entrypoint wrapper script. You can write a shell script that does the startup-time setup, and then switches to the main container command. This runs at container startup, so it's after the volume is created and mounted.

    #!/bin/sh
    if [ ! -d /config/webapp ]; then
      mkdir /config/webapp || exit 1
    fi
    if [ ! -d /config/webapp/cleanup_script ]; then
      mkdir /config/webapp/cleanup_script || exit 1
    fi
    if [ ! -f /config/webapp/cleanup_script/file.py ]; then
      cp /repo/file.py /config/webapp/cleanup_script || exit 1
    fi
    
    exec "$@"
    

    In your Dockerfile, make this script be the ENTRYPOINT. The ENTRYPOINT line must use the JSON-array syntax. Leave your CMD unchanged.

    ENTRYPOINT ["./entrypoint.sh"]
    CMD ["./webapp"]
    

    This will work so long as the config directory is writable. You mention Kubernetes; an emptyDir volume will work (but won't survive restarts), or you can create a PersistentVolumeClaim via a StatefulSet, but you can't mount a ConfigMap here because it won't be writable.