Why does Mac OSX still exhibit case insensitivity when using Docker Desktop for Mac
Asked Answered
E

2

7

I am using Docker Desktop for Mac to containerize a basic LAMP stack in my local environment, then periodically deploying a simple MVC application to a shared Linux server using a Bitbucket pipeline.

Everything is behaving as expected apart from the router. When in prod, the autoload fails because the Linux environment distinguishes between the routes, App/Controllers/Posts and app/controllers/posts, for example. I realise that for PSR-4 autoloading to work, the case of each folder / namespace and file / class have to match, and clearly the reason it's failing in prod is because of the live environment's case sensitivity highlighting this mismatch.

However, the obvious reason for using Docker is to avoid these differing behaviours in local and prod environments. Is it definitely the case that using Docker on a Mac won't exhibit case sensitivity, even when in a container based on an Ubuntu image, for instance, so that I can pick up on these issues locally without having to test in prod? An issue raised on Github (https://github.com/docker/for-mac/issues/320 back in 2016) suggests that this is not possible due to Mac’s "osxfs”. However, when looking at the Docker for Mac docs (https://docs.docker.com/docker-for-mac/) it would appear that it should pick up on this; specifically:

By default, Mac file systems are case-insensitive while Linux is case-sensitive. On Linux, it is possible to create 2 separate files: test and Test, while on Mac these filenames would actually refer to the same underlying file. This can lead to problems where an app works correctly on a Mac (where the file contents are shared) but fails when run in Linux in production (where the file contents are distinct). To avoid this, Docker Desktop insists that all shared files are accessed as their original case. Therefore, if a file is created called test, it must be opened as test...

(bold added by me)

Does this not indicate that case sensitivity should be exhibited, or am I reading the docs incorrectly? For the record, here is my Dockerfile and docker-compose file:

FROM php:7.4-apache

RUN a2enmod rewrite

RUN apt-get update
RUN apt-get install git -y
RUN apt-get install -y libzip-dev zip

RUN docker-php-ext-install pdo pdo_mysql

RUN curl -sS https://getcomposer.org/installer | php
RUN mv composer.phar /usr/local/bin/composer

WORKDIR /var/www/developmental

COPY .docker/vhost.conf /etc/apache2/sites-available/000-default.conf
version: "3.8"

services:
  php:
    build:
      context: .
      dockerfile: ./.docker/Dockerfile
    ports:
      - 8080:80
    volumes:
      - .:/var/www/developmental

  db:
    image: mysql/mysql-server
    command: --default-authentication-plugin=mysql_native_password
    ports:
      - 3308:3306
    environment:
      MYSQL_ROOT_PASSWORD: "${DB_ROOT_PASSWORD}"
    volumes:
      - db-data:/var/lib/mysql
      - ./data:/docker-entrypoint-initdb.d

volumes:
  db-data:

Many thanks in advance (and go easy - I'm a Docker rookie and this is my first Stackoverflow question!)

Eaton answered 2/11, 2020 at 12:15 Comment(2)
The volumes: bind mount is a pass through from the host system, so you can run into problems like this. It'd be more reliable to COPY your code into the image and remove that bind mount; then the container filesystem will be entirely in Linux space.Perilous
Thanks @DavidMaze, this has resolved the issue.Eaton
P
6

Since you're bind-mounting a directory from the host into the container, it comes along with any irregularities the host filesystem might have; for example the paragraph you quoted about case-insensitivity on MacOS.

It's often better to make a Docker image be self-contained: write a Dockerfile that COPY all of the required application code into the image, and avoid this bind mount entirely. If you do this, then the application code will be only in the case-sensitive Linux filesystem. If you need to correct the case of filenames you can RUN mv foo Foo for example.

# In the Dockerfile
...
WORKDIR /var/www/developmental
COPY . .
# In docker-compose.yml
services:
  php:
    build:
      context: .
      dockerfile: ./.docker/Dockerfile
    ports:
      - 8080:80
    # and remove `volumes:`
Perilous answered 2/11, 2020 at 15:15 Comment(1)
Thanks for the explanation. I removed the volume mounting and copied the application code into the image via the Dockerfile which resolved the issue of OSX/Linux case sensitivity disparity. However, after my previous comment, I realised that I need the shared volumes so that I can see the reflected code changes (made via my IDE on the host) without having to rebuild the container. The only way around this (as far as my novice knowledge takes me) would be to run an IDE from within the container... unless there's something I'm missing...Eaton
D
3

One way to solve this on modern Mac APFS based systems is to create a case-sensitive volume where you store you store your docker volume data. The following will create a new volume that which is case-sensitive (APFSX) that you can use for your volume data. Note: You should do this in a fresh directory.

mkdir <docker volume directory>
sudo diskutil apfs addVolume disk1 APFSX docker -mountpoint <docker volume directory>
sudo chown -R $(id -u):$(id -g) <docker volume directory>

Ref: Feature to opt-in into a case sensitive file-system (osxfs) on a volume mount

Dalston answered 3/11, 2021 at 15:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.