Scrambledheads
Scrambledheads

Reputation: 129

Docker compose mapping local directory to dockerfile volume

I'm using an Apache / MySql Docker-compose set up which is all good. However the issue comes when, as this is for local development, the web container points to a local folder, for which I need Apache to have permissions to.

Using

RUN mkdir /www \
&& chown -R apache:apache /www

VOLUME ["/www"]

is fine if I run the Apache dockerfile by itself or if I run it in docker-compose without specifying a volume. But this means that I can't point that volume at a local directory, in this scenario "www" exists inside the container but doesn't map to the host machine. If I specify a volume inside the docker-compose file then it maps as expected but doesn't allow me to CHOWN the folder / files (even if I exec into the container)

Below is a proof of concept, I'm running on Windows 10 / Docker Desktop Community Version 2.0.0.0-win81 (29211)

EDIT (commented exposing the port, built the dockerfile from docker-compose and changed the port to 80 from 81)

EDIT (I've updated the following files, see bottom, I'm leaving these for posterity)

docker-compose.yml

version: '3.2'
services:
  web:
    restart: always
    build:
      context: .
    ports:
      - 80:80
    volumes: 
    - ./:/www

Dockerfile

FROM centos:centos6 as stage1

RUN yum -y update && yum clean all \
    && yum --setopt=tsflags=nodocs install -y yum-utils \
    httpd \
    php

FROM stage1 as stage2
RUN mkdir /www \
    && chown -R apache:apache /www 

#VOLUME ["/www"]

#EXPOSE 80
ENTRYPOINT ["/usr/sbin/httpd", "-D", "FOREGROUND"]

UPDATED Proof of concept files

Docker-compose.yml

version: '3.2'
services:
  web:
    build:
      context: .
    ports:
      - 80:80
    volumes: 
    - ./:/www

Dockerfile

FROM centos:centos6

RUN yum -y update && yum clean all \
    && yum --setopt=tsflags=nodocs install -y yum-utils \
    httpd \
    php

COPY ./entrypoint.sh /

ENTRYPOINT ["/entrypoint.sh"]

entrypoint.sh

#!/bin/bash
set -e #exit straight away if there's an issue

chown -R apache:apache /www

# Apache
/usr/sbin/httpd -D FOREGROUND

Upvotes: 4

Views: 11826

Answers (2)

Bret Fisher
Bret Fisher

Reputation: 8616

Docker for Windows uses a CIFS/Samba network file share to bind-mount host files into the Linux VM running docker. That is always done as root:root so all bind-mount files/dirs will always show that when seen from inside container. This is a known limitation of the way docker shares these files between the OS's.

Workarounds:

  1. In many cases, this isn't an issue. The host files are shared into the container world-readable, so local app development while running in the container is fine. For cache files, user uploads, etc. just be sure they are written into a container path that isn't to the host-bind mount, so they stay in Linux where you can control the perms.
  2. If needed, for development only, run the app in the container as root if it needs write permissions to host OS files. You can override this at runtime: e.g. docker run -u root or user:root in docker-compose.yml
  3. For working with database files, don't bind-mount them, but use named volumes to keep the files in the Linux VM. You can always use docker cp to copy files in and out of volumes for a quick backup.

Upvotes: 1

Shardj
Shardj

Reputation: 1969

You're using

RUN mkdir /www \ && chown -R apache:apache /www

Prior to docker-compose mapping the local . directory to www.

You need to create a file entrypoint.sh or similar. Give it a shbang. And inside that you should run chown -R apache:apache /www. You do not need the mkdir as that's created by docker compose volume config ./:/www.

After that command in your entrypoint.sh file you should add in what you currently have for your entrypoint /usr/sbin/httpd -D FOREGROUND.

Then finally you of course need to set your new entrypoint to use the entrypoint.sh file ENTRYPOINT ["/entrypoint.sh"]

Upvotes: 1

Related Questions