Skip to content

Commit

Permalink
feat: Use dedicated images for php and nginx, aligned workdirs (#4)
Browse files Browse the repository at this point in the history
* feat: Use dedicated images for php and nginx, aligned workdirs

* chore: Only enable nginx healthcheck if ready

* Apply suggestions from code review

Co-authored-by: Eliot <[email protected]>

---------

Co-authored-by: Eliot <[email protected]>
  • Loading branch information
ambroisemaupate and eliot488995568 authored Dec 5, 2024
1 parent 5e50725 commit 464b4ac
Show file tree
Hide file tree
Showing 18 changed files with 462 additions and 88 deletions.
2 changes: 1 addition & 1 deletion .env
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
# https://symfony.com/doc/current/best_practices.html#use-environment-variables-for-infrastructure-configuration

# Main user is 1000 on Linux
USER_UID=1000
UID=1000
PUBLIC_NGINX_PORT=8781
PUBLIC_VARNISH_PORT=8784
PUBLIC_PMA_PORT=8782
Expand Down
127 changes: 95 additions & 32 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
ARG PHP_VERSION=8.3.14
ARG MYSQL_VERSION=8.0.40
ARG NGINX_VERSION=1.27.2
ARG SOLR_VERSION=9
ARG VARNISH_VERSION=7.1
ARG USER_UID=1000
ARG UID=1000

#######
# PHP #
Expand All @@ -12,7 +13,7 @@ FROM php:${PHP_VERSION}-fpm-bookworm AS php

LABEL org.opencontainers.image.authors="[email protected]"

ARG USER_UID
ARG UID

ARG COMPOSER_VERSION=2.8.1
ARG PHP_EXTENSION_INSTALLER_VERSION=2.6.0
Expand All @@ -24,8 +25,6 @@ ENV APP_FFMPEG_PATH=/usr/bin/ffmpeg
ENV MYSQL_HOST=db
ENV MYSQL_PORT=3306

HEALTHCHECK --start-period=30s --interval=1m --timeout=6s CMD bin/console monitor:health -q

COPY --link docker/php/crontab.txt /crontab.txt
COPY --link docker/php/wait-for-it.sh /wait-for-it.sh
COPY --link docker/php/fpm.d/www.conf ${PHP_INI_DIR}-fpm.d/zz-www.conf
Expand All @@ -42,13 +41,17 @@ apt-get --quiet --yes --no-install-recommends --verbose-versions install \
ffmpeg
rm -rf /var/lib/apt/lists/*

usermod -u ${USER_UID} www-data
groupmod -g ${USER_UID} www-data
echo "www-data ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/www-data
# User
addgroup --gid ${UID} php
adduser --home /home/php --shell /bin/bash --uid ${UID} --gecos php --ingroup php --disabled-password php
echo "php ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/php

/usr/bin/crontab -u www-data /crontab.txt
# App
install --verbose --owner php --group php --mode 0755 --directory /app

/usr/bin/crontab -u php /crontab.txt
chmod +x /wait-for-it.sh
chown -R www-data:www-data /var/www/html
chown -R php:php /app

# Php extensions
curl -sSLf https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions \
Expand All @@ -75,7 +78,7 @@ install-php-extensions \
redis-${PHP_EXTENSION_REDIS_VERSION}
EOF

WORKDIR /var/www/html
WORKDIR /app

###################
# PHP Development #
Expand Down Expand Up @@ -105,12 +108,12 @@ apt-get --quiet --yes --purge --autoremove upgrade
apt-get --quiet --yes --no-install-recommends --verbose-versions install make
rm -rf /var/lib/apt/lists/*
# Prepare folder to install composer credentials
install --owner=www-data --group=www-data --mode=755 --directory /var/www/.composer
install --owner=php --group=php --mode=755 --directory /home/php/.composer
EOF

VOLUME /var/www/html
VOLUME /app

USER www-data
USER php

# If you depend on private Gitlab repositories, you must use a deploy token and username
#RUN composer config --global gitlab-token.gitlab.rezo-zero.com ${COMPOSER_DEPLOY_TOKEN_USER} ${COMPOSER_DEPLOY_TOKEN}
Expand Down Expand Up @@ -138,17 +141,17 @@ COPY --link docker/php/conf.d/php.prod.ini ${PHP_INI_DIR}/conf.d/zz-app.ini
COPY --link --chmod=755 docker/php/docker-php-entrypoint /usr/local/bin/docker-php-entrypoint
COPY --link --chmod=755 docker/php/docker-cron-entrypoint /usr/local/bin/docker-cron-entrypoint

USER www-data
USER php

# Composer
COPY --link --chown=www-data:www-data composer.* symfony.* ./
COPY --link --chown=php:php composer.* symfony.* ./
RUN <<EOF
# If you depend on private Gitlab repositories, you must use a deploy token and username
#composer config gitlab-token.gitlab.rezo-zero.com ${COMPOSER_DEPLOY_TOKEN_USER} ${COMPOSER_DEPLOY_TOKEN}
composer install --no-cache --prefer-dist --no-dev --no-autoloader --no-scripts --no-progress
EOF

COPY --link --chown=www-data:www-data . .
COPY --link --chown=php:php . .

RUN <<EOF
composer dump-autoload --classmap-authoritative --no-dev
Expand All @@ -157,23 +160,83 @@ bin/console assets:install
bin/console themes:assets:install Rozier
EOF

VOLUME /var/www/html/config/jwt \
/var/www/html/config/secrets \
/var/www/html/public/files \
/var/www/html/public/assets \
/var/www/html/var/files
HEALTHCHECK --start-period=30s --interval=1m --timeout=6s CMD bin/console monitor:health -q

VOLUME /app/config/jwt \
/app/config/secrets \
/app/public/files \
/app/public/assets \
/app/var/files



#########
# Nginx #
#########

FROM roadiz/nginx-alpine AS nginx-prod
FROM nginx:${NGINX_VERSION}-bookworm AS nginx

LABEL org.opencontainers.image.authors="[email protected]"

COPY --link --from=php-prod --chown=www-data:www-data /var/www/html/public /var/www/html/public
ARG UID

SHELL ["/bin/bash", "-e", "-o", "pipefail", "-c"]

RUN <<EOF
# Packages
apt-get --quiet update
apt-get --quiet --yes --purge --autoremove upgrade
apt-get --quiet --yes --no-install-recommends --verbose-versions install \
less \
sudo
rm -rf /var/lib/apt/lists/*

# User
groupmod --gid ${UID} nginx
usermod --uid ${UID} nginx
echo "nginx ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/nginx

# App
install --verbose --owner nginx --group nginx --mode 0755 --directory /app
EOF

ENV NGINX_ENTRYPOINT_QUIET_LOGS=1
# Config
COPY --link docker/nginx/nginx.conf /etc/nginx/nginx.conf
COPY --link docker/nginx/redirections.conf /etc/nginx/redirections.conf
COPY --link docker/nginx/mime.types /etc/nginx/mime.types
COPY --link docker/nginx/conf.d/_gzip.conf /etc/nginx/conf.d/_gzip.conf
COPY --link docker/nginx/conf.d/_security.conf /etc/nginx/conf.d/_security.conf
COPY --link docker/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf

WORKDIR /app



##############
# Nginx DEV #
##############

FROM nginx AS nginx-dev

# Silence entrypoint logs

# Declare a volume for development
VOLUME /app



##############
# Nginx PROD #
##############

FROM nginx AS nginx-prod
# Copy public files from API
COPY --link --from=php-prod --chown=${USER_UID}:${USER_UID} /app/public /app/public

# Only enable healthcheck in production when the app is ready to serve requests on root path
# This could prevent Traefik or an ingress controller to route traffic to the app
#HEALTHCHECK --start-period=1m30s --interval=1m --timeout=6s CMD curl --fail -I http://localhost

#########
# MySQL #
Expand All @@ -183,14 +246,14 @@ FROM mysql:${MYSQL_VERSION} AS mysql

LABEL org.opencontainers.image.authors="[email protected]"

ARG USER_UID
ARG UID

SHELL ["/bin/bash", "-e", "-o", "pipefail", "-c"]

RUN <<EOF
usermod -u ${USER_UID} mysql
groupmod -g ${USER_UID} mysql
echo "USER_UID: ${USER_UID}\n"
usermod -u ${UID} mysql
groupmod -g ${UID} mysql
echo "UID: ${UID}\n"
EOF

COPY --link docker/mysql/performances.cnf /etc/mysql/conf.d/performances.cnf
Expand All @@ -203,18 +266,18 @@ FROM solr:${SOLR_VERSION}-slim AS solr

LABEL org.opencontainers.image.authors="[email protected]"

ARG USER_UID
ARG UID

SHELL ["/bin/bash", "-e", "-o", "pipefail", "-c"]

USER root

RUN <<EOF
set -ex
echo "USER_UID: ${USER_UID}\n"
usermod -u ${USER_UID} "$SOLR_USER"
groupmod -g ${USER_UID} "$SOLR_GROUP"
chown -R ${USER_UID}:${USER_UID} /var/solr
echo "UID: ${UID}\n"
usermod -u ${UID} "$SOLR_USER"
groupmod -g ${UID} "$SOLR_GROUP"
chown -R ${UID}:${UID} /var/solr
EOF

COPY --link docker/solr/managed-schema.xml /opt/solr/server/solr/configsets/_default/conf/managed-schema
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ services:
#app:
# build:
# args:
# USER_UID: ${USER_UID}
# UID: ${UID}
# COMPOSER_DEPLOY_TOKEN: xxxxxxxxxxxxx
# COMPOSER_DEPLOY_TOKEN_USER: "gitlab+deploy-token-1"

Expand Down
2 changes: 1 addition & 1 deletion compose.override.yml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ services:
#app:
# build:
# args:
# USER_UID: ${USER_UID}
# UID: ${UID}
# COMPOSER_DEPLOY_TOKEN: xxxxxxxxxxxxx
# COMPOSER_DEPLOY_TOKEN_USER: "gitlab+deploy-token-1"

Expand Down
28 changes: 14 additions & 14 deletions compose.prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,9 @@ services:
networks:
- default
volumes:
- ./robots.txt:/var/www/html/public/robots.txt:ro
- app_file_data:/var/www/html/public/files:ro
- app_assets_data:/var/www/html/public/assets:ro
- ./robots.txt:/app/public/robots.txt:ro
- app_file_data:/app/public/files:ro
- app_assets_data:/app/public/assets:ro
labels:
- "com.centurylinklabs.watchtower.enable=true"
- "com.centurylinklabs.watchtower.depends-on=/skeleton-app-1"
Expand All @@ -118,24 +118,24 @@ services:
- redis
#- solr
volumes:
- app_file_data:/var/www/html/public/files
- app_assets_data:/var/www/html/public/assets
- app_private_file_data:/var/www/html/var/files
- app_secret_data:/var/www/html/config/secrets
- app_file_data:/app/public/files
- app_assets_data:/app/public/assets
- app_private_file_data:/app/var/files
- app_secret_data:/app/config/secrets
## Use docker-compose env file as .env.local in container
- ./.env:/var/www/html/.env.local:ro
- ./.env:/app/.env.local:ro
## Generate JWT certificates on your host and share them to docker container
## openssl genpkey -out jwt_private.pem -aes256 -algorithm rsa -pkeyopt rsa_keygen_bits:4096; chmod 0644 jwt_private.pem;
- ./jwt_private.pem:/var/www/html/config/jwt/private.pem:ro
- ./jwt_private.pem:/app/config/jwt/private.pem:ro
## openssl pkey -in jwt_private.pem -out jwt_public.pem -pubout; chmod 0644 jwt_public.pem;
- ./jwt_public.pem:/var/www/html/config/jwt/public.pem:ro
- ./jwt_public.pem:/app/config/jwt/public.pem:ro
##
## Do not add volume for src/GeneratedEntity, they are versioned since Roadiz v2
## Uncomment these if you DO want to persist and edit node-types on production env
##
#- app_node_types_api:/var/www/html/config/api_resources
#- app_node_types_resource:/var/www/html/src/Resources
#- app_node_types_entities:/var/www/html/src/GeneratedEntity
#- app_node_types_api:/app/config/api_resources
#- app_node_types_resource:/app/src/Resources
#- app_node_types_entities:/app/src/GeneratedEntity
networks:
- default
environment:
Expand All @@ -156,7 +156,7 @@ services:
# Do not use more than 1 replica if you're using Varnish and need to purge/ban cache
# from your workers. Varnish ACL hostnames won't be resolved correctly.
replicas: 1
entrypoint: [ "php", "/var/www/html/bin/console", "messenger:consume", "async", "--time-limit=1800" ]
entrypoint: [ "php", "/app/bin/console", "messenger:consume", "async", "--time-limit=1800" ]

cron:
<<: *app_template
Expand Down
22 changes: 11 additions & 11 deletions compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ services:
# Custom image for file permissions and performances
target: mysql
args:
USER_UID: ${USER_UID}
UID: ${UID}
cap_add:
- SYS_NICE # CAP_SYS_NICE
networks:
Expand Down Expand Up @@ -54,26 +54,29 @@ services:
build:
target: php-dev
args:
USER_UID: ${USER_UID}
UID: ${UID}
depends_on:
- db
- solr
- redis
volumes:
- ./:/var/www/html
- ./:/app
networks:
default:
environment:
TRUSTED_PROXIES: ${TRUSTED_PROXIES}
USER_UID: ${USER_UID}
UID: ${UID}
DEFAULT_GATEWAY: ${DEFAULT_GATEWAY}

nginx:
image: roadiz/nginx-alpine:latest
build:
target: nginx-dev
args:
UID: ${UID}
depends_on:
- app
volumes:
- ./:/var/www/html
- ./:/app
networks:
default:
# frontproxynet:
Expand Down Expand Up @@ -110,7 +113,7 @@ services:
replicas: 1
# official php-fpm image uses SIGQUIT
stop_signal: SIGTERM
entrypoint: [ "php", "/var/www/html/bin/console", "messenger:consume", "async", "--time-limit=600" ]
entrypoint: [ "php", "/app/bin/console", "messenger:consume", "async", "--time-limit=600" ]
restart: unless-stopped

cron:
Expand All @@ -127,12 +130,9 @@ services:
# Custom image for file permissions
target: solr
args:
USER_UID: ${USER_UID}
UID: ${UID}
volumes:
- "solr:/var/solr"
environment:
SOLR_UID: ${USER_UID}
SOLR_GID: ${USER_UID}
command:
- solr-precreate
- ${SOLR_CORE_NAME}
Expand Down
14 changes: 14 additions & 0 deletions docker/nginx/conf.d/_gzip.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
gzip on;
gzip_proxied any;
gzip_vary on;
gzip_comp_level 2;
gzip_min_length 256;
gzip_types application/atom+xml application/javascript application/json application/rss+xml
application/vnd.ms-fontobject application/x-font-opentype application/x-font-truetype
application/x-font-ttf application/x-javascript application/xhtml+xml application/xml
font/eot font/opentype font/otf font/truetype image/svg+xml image/vnd.microsoft.icon
image/x-icon image/x-win-bitmap text/css text/javascript text/plain text/xml;
gzip_disable "MSIE [1-6]\.(?!.*SV1)";
# make sure gzip does not lose large gzipped js or css files
# see http://blog.leetsoft.com/2007/7/25/nginx-gzip-ssl
gzip_buffers 16 8k;
Loading

0 comments on commit 464b4ac

Please sign in to comment.