From 88c52db53c2b010cdc1fc8933d0ca8f54a758080 Mon Sep 17 00:00:00 2001 From: Yassine Doghri <yassine@doghri.fr> Date: Mon, 24 May 2021 10:08:15 +0000 Subject: [PATCH] build(docker): optimize Dockerfile and setup vscode devcontainer with all required dependencies - fix: set mediaBaseURL as baseURL if not defined - update dev documentation seting up a dev environment --- .devcontainer/devcontainer.json | 7 ++- .devcontainer/docker-compose.yml | 10 ++++ Dockerfile | 84 +++++++++++++-------------- app/Controllers/InstallController.php | 2 +- app/Helpers/media_helper.php | 8 ++- docker-compose.yml | 11 ++-- docs/setup-development.md | 65 +++++++++++++++++---- 7 files changed, 123 insertions(+), 64 deletions(-) create mode 100644 .devcontainer/docker-compose.yml diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 621ed45dbc..84e45dd03e 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -2,10 +2,13 @@ // https://github.com/microsoft/vscode-dev-containers/tree/v0.117.1/containers/docker-existing-dockerfile { "name": "Castopod Host dev", - "dockerComposeFile": ["../docker-compose.yml"], + "dockerComposeFile": ["../docker-compose.yml", "./docker-compose.yml"], "service": "app", "workspaceFolder": "/castopod-host", - "postCreateCommand": "cron && php spark serve --host 0.0.0.0", + "postCreateCommand": "composer install && npm install && npm run build:dev", + "postStartCommand": "crontab ./crontab && cron && php spark serve --host 0.0.0.0", + "postAttachCommand": "crontab ./crontab && service cron reload", + "shutdownAction": "stopCompose", "settings": { "terminal.integrated.defaultProfile.linux": "/bin/bash", "editor.formatOnSave": true, diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml new file mode 100644 index 0000000000..c7323a5b52 --- /dev/null +++ b/.devcontainer/docker-compose.yml @@ -0,0 +1,10 @@ +version: "3" +services: + app: + volumes: + # Mounts the project folder to '/workspace'. While this file is in .devcontainer, + # mounts are relative to the first file in the list, which is a level up. + - .:/castopod-host:cached + + # Overrides default command so things don't shut down after the process ends. + command: /bin/sh -c "while sleep 1000; do :; done" diff --git a/Dockerfile b/Dockerfile index 9c58eae0f9..9eb3536d74 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,9 @@ #################################################### # Castopod Host development Docker file #################################################### -# NOT optimized for production +# âš ï¸ NOT optimized for production # should be used only for development purposes -#################################################### - +#--------------------------------------------------- FROM php:8.0-fpm LABEL maintainer="Yassine Doghri <yassine@doghri.fr>" @@ -13,50 +12,51 @@ COPY . /castopod-host WORKDIR /castopod-host # Install composer -COPY --from=composer:latest /usr/bin/composer /usr/bin/composer - -# Install latest npm -RUN apt-get update && \ - apt-get install -y --no-install-recommends gnupg && \ - curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - && \ - apt-get update && \ - apt-get install -y --no-install-recommends nodejs && \ - npm install --global npm - -# Install git + vim -RUN apt-get update && \ - apt-get upgrade -y && \ - apt-get install -y git vim - -### Install CodeIgniter's server requirements -#-- https://github.com/codeigniter4/appstarter#server-requirements - -# Install intl extension using https://github.com/mlocati/docker-php-extension-installer -RUN apt-get update && apt-get install -y \ +COPY --from=composer:2 /usr/bin/composer /usr/bin/composer + +# Install server requirements +RUN apt-get update \ + # gnupg to sign commits with gpg + && apt-get install --yes --no-install-recommends gnupg \ + # npm through the nodejs package + && curl -fsSL https://deb.nodesource.com/setup_14.x | bash - \ + && apt-get update \ + && apt-get install --yes --no-install-recommends nodejs \ + # update npm + && npm install --global npm@7 \ + && apt-get update \ + && apt-get install --yes --no-install-recommends \ + git \ + openssh-client \ + vim \ + # cron for scheduled tasks + cron \ + # unzip used by composer + unzip \ + # required libraries to install php extensions using + # https://github.com/mlocati/docker-php-extension-installer (included in php's docker image) libicu-dev \ libpng-dev \ libjpeg-dev \ zlib1g-dev \ - && docker-php-ext-install intl - -RUN docker-php-ext-configure gd --with-jpeg \ - && docker-php-ext-install gd - -RUN pecl install -o -f redis \ - && rm -rf /tmp/pear \ - && docker-php-ext-enable redis - -RUN docker-php-ext-install mysqli && docker-php-ext-enable mysqli - -RUN echo "file_uploads = On\n" \ + libzip-dev \ + # intl for Internationalization + && docker-php-ext-install intl \ + && docker-php-ext-install zip \ + # gd for image processing + && docker-php-ext-configure gd --with-jpeg \ + && docker-php-ext-install gd \ + # redis extension for cache + && pecl install -o -f redis \ + && rm -rf /tmp/pear \ + && docker-php-ext-enable redis \ + # mysqli for database access + && docker-php-ext-install mysqli \ + && docker-php-ext-enable mysqli \ + # configure php + && echo "file_uploads = On\n" \ "memory_limit = 512M\n" \ "upload_max_filesize = 500M\n" \ "post_max_size = 512M\n" \ "max_execution_time = 300\n" \ - > /usr/local/etc/php/conf.d/uploads.ini - -# install cron -RUN apt-get update && \ - apt-get install -y cron - -RUN crontab /castopod-host/crontab + > /usr/local/etc/php/conf.d/uploads.ini \ diff --git a/app/Controllers/InstallController.php b/app/Controllers/InstallController.php index 9b6f92082c..8e80b35dfc 100644 --- a/app/Controllers/InstallController.php +++ b/app/Controllers/InstallController.php @@ -163,7 +163,7 @@ class InstallController extends Controller self::writeEnv([ 'app.baseURL' => $baseUrl, 'app.mediaBaseURL' => - $mediaBaseUrl === null ? $baseUrl : $mediaBaseUrl, + $mediaBaseUrl === '' ? $baseUrl : $mediaBaseUrl, 'app.adminGateway' => $this->request->getPost('admin_gateway'), 'app.authGateway' => $this->request->getPost('auth_gateway'), ]); diff --git a/app/Helpers/media_helper.php b/app/Helpers/media_helper.php index 18b03f2e89..17df25714a 100644 --- a/app/Helpers/media_helper.php +++ b/app/Helpers/media_helper.php @@ -117,10 +117,12 @@ if (! function_exists('media_base_url')) { } $uri = trim($uri, '/'); - return rtrim(config('App')->mediaBaseURL, '/') . + $appConfig = config('App'); + $mediaBaseUrl = $appConfig->mediaBaseURL === '' ? $appConfig->baseURL : $appConfig->mediaBaseURL; + + return rtrim($mediaBaseUrl, '/') . '/' . - config('App') - ->mediaRoot . + $appConfig->mediaRoot . '/' . $uri; } diff --git a/docker-compose.yml b/docker-compose.yml index 7b138da1b8..4142285e49 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,9 +8,8 @@ services: build: context: . dockerfile: Dockerfile - container_name: castopod_host - command: > - sh -c "cron && php spark serve --host 0.0.0.0" + container_name: castopod-host + command: /bin/sh -c "crontab ./crontab && cron && service cron reload && php spark serve --host 0.0.0.0" ports: - 8080:8080 volumes: @@ -23,7 +22,7 @@ services: redis: image: redis:alpine - container_name: castopod_host_redis + container_name: castopod-host_redis ports: - 6379:6379 volumes: @@ -33,7 +32,7 @@ services: mariadb: image: mariadb:latest - container_name: castopod_host_mariadb + container_name: castopod-host_mariadb ports: - 3306:3306 volumes: @@ -48,7 +47,7 @@ services: phpmyadmin: image: phpmyadmin/phpmyadmin:latest - container_name: castopod_host_phpmyadmin + container_name: castopod-host_phpmyadmin environment: PMA_HOST: mariadb PMA_PORT: 3306 diff --git a/docs/setup-development.md b/docs/setup-development.md index a65c178f4a..838b9e7506 100644 --- a/docs/setup-development.md +++ b/docs/setup-development.md @@ -12,6 +12,8 @@ - [Going Further](#going-further) - [Useful docker / docker-compose commands](#useful-docker--docker-compose-commands) - [Known issues](#known-issues) + - [Allocation failed - JavaScript heap out of memory](#allocation-failed---javascript-heap-out-of-memory) + - [Files created inside container are attributed to root locally (Linux)](#files-created-inside-container-are-attributed-to-root-locally-linux) ## Introduction @@ -74,7 +76,7 @@ to help you kickstart your contribution. 3. (for docker desktop) Add the repository you've cloned to docker desktop's `Settings` > `Resources` > `File Sharing` -### (recommended) Develop inside the app Container with VSCode +## (recommended) Develop inside the app Container with VSCode If you're working in VSCode, you can take advantage of the `.devcontainer/` folder. It defines a development environment (dev container) with preinstalled @@ -110,7 +112,7 @@ required services will be loaded automagically! For more info, see [VSCode Remote Containers](https://code.visualstudio.com/docs/remote/containers) -### (not-recommended) Develop outside the app container +## (not-recommended) Develop outside the app container You do not wish to use the VSCode devcontainer? No problem! @@ -134,13 +136,13 @@ You do not wish to use the VSCode devcontainer? No problem! > The `docker-compose up -d` command will boot 4 containers in the > background: > - > - `castopod_host_app`: a php based container with CodeIgniter4 requirements + > - `castopod-host_app`: a php based container with CodeIgniter4 requirements > installed - > - `castopod_host_redis`: a [redis](https://redis.io/) database to handle + > - `castopod-host_redis`: a [redis](https://redis.io/) database to handle > queries and pages caching - > - `castopod_host_mariadb`: a [mariadb](https://mariadb.org/) server for + > - `castopod-host_mariadb`: a [mariadb](https://mariadb.org/) server for > persistent data - > - `castopod_host_phpmyadmin`: a phpmyadmin server to visualize the mariadb + > - `castopod-host_phpmyadmin`: a phpmyadmin server to visualize the mariadb > database. 2. Run any command by prefixing them with `docker-compose run --rm app`: @@ -292,7 +294,7 @@ To see your changes, go to: docker-compose logs --tail 50 --follow --timestamps app # interact with redis server using included redis-cli command -docker exec -it castopod_host_redis redis-cli +docker exec -it castopod-host_redis redis-cli # monitor the redis container docker-compose logs --tail 50 --follow --timestamps redis @@ -319,7 +321,50 @@ more insights. ## Known issues -- `Allocation failed - JavaScript heap out of memory` when running `npm install` +### Allocation failed - JavaScript heap out of memory - 👉 By default, docker might not have access to enough RAM. Allocate more - memory and run `npm install` again. +This happens when running `npm install`. + +👉 By default, docker might not have access to enough RAM. Allocate more memory +and run `npm install` again. + +### Files created inside container are attributed to root locally (Linux) + +You may use Linux user namespaces to fix this: + +> **Note:** +> +> Replace "username" with your local username + +1. Go to `/etc/docker/daemon.json` and add: + + ```json + { + "userns-remap": "username" + } + ``` + +2. Configure the subordinate uid/guid: + + ```bash + username:1000:1 + username:100000:65536 + ``` + + ```bash + username:1000:1 + username:100000:65536 + ``` + +3. Restart docker: + + ```bash + sudo systemctl restart docker + ``` + +4. That's it! Now, the root user in the container will be mapped to the user on + your local machine, no more permission problems! 🎉 + +You can check +[this great article](https://www.jujens.eu/posts/en/2017/Jul/02/docker-userns-remap/) +to know more about how it works. -- GitLab