From 2e149d1650a677d4789c3300b61fc8769fc7845f Mon Sep 17 00:00:00 2001 From: Lee Peuker Date: Sun, 5 Nov 2023 18:02:13 +0100 Subject: [PATCH 1/3] Set up own php+nginx+supervisor dockerfile --- .dockerignore | 1 - Makefile | 20 ++++----- build/Dockerfile | 73 ++++++++++++++++++++++++++++++++ build/config/conf.d/default.conf | 57 +++++++++++++++++++++++++ build/config/fpm-pool.conf | 56 ++++++++++++++++++++++++ build/config/nginx.conf | 45 ++++++++++++++++++++ build/config/php.ini | 3 ++ build/config/supervisord.conf | 35 +++++++++++++++ build/php/Dockerfile | 15 ------- docker-compose.yml | 5 +-- settings/supervisor/movary.conf | 12 ------ 11 files changed, 281 insertions(+), 41 deletions(-) create mode 100644 build/Dockerfile create mode 100644 build/config/conf.d/default.conf create mode 100644 build/config/fpm-pool.conf create mode 100644 build/config/nginx.conf create mode 100644 build/config/php.ini create mode 100644 build/config/supervisord.conf delete mode 100644 build/php/Dockerfile delete mode 100644 settings/supervisor/movary.conf diff --git a/.dockerignore b/.dockerignore index 3316bb3e1..b8827d91d 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,4 +1,3 @@ -build/ tests/ public/images/cached/* tmp/* diff --git a/Makefile b/Makefile index 02571f36b..3fdb08fb6 100644 --- a/Makefile +++ b/Makefile @@ -25,24 +25,24 @@ logs: build: docker compose build --no-cache make up - make db_mysql_create_database + #make db_mysql_create_database make composer_install - make app_database_migrate - make exec_app_cmd CMD="php bin/console.php storage:link" +# make app_database_migrate +# make exec_app_cmd CMD="php bin/console.php storage:link" # Container interaction ####################### -exec_app_bash: - docker compose exec app bash +exec_app_sh: + docker compose exec app sh exec_app_cmd: - docker compose exec app bash -c "${CMD}" + docker compose exec app sh -c "${CMD}" exec_mysql_cli: docker compose exec mysql sh -c "mysql -u${DB_USER} -p${DB_PASSWORD} ${DATABASE_MYSQL_NAME}" exec_mysql_query: - docker compose exec mysql bash -c "mysql -uroot -p${DATABASE_MYSQL_ROOT_PASSWORD} -e \"$(QUERY)\"" + docker compose exec mysql sh -c "mysql -uroot -p${DATABASE_MYSQL_ROOT_PASSWORD} -e \"$(QUERY)\"" # Composer ########## @@ -65,10 +65,10 @@ db_mysql_create_database: db_mysql_import: docker cp storage/dump.sql movary_mysql_1:/tmp/dump.sql - docker compose exec mysql bash -c 'mysql -uroot -p${DATABASE_MYSQL_ROOT_PASSWORD} < /tmp/dump.sql' + docker compose exec mysql sh -c 'mysql -uroot -p${DATABASE_MYSQL_ROOT_PASSWORD} < /tmp/dump.sql' db_mysql_export: - docker compose exec mysql bash -c 'mysqldump --databases --add-drop-database -uroot -p$(DATABASE_MYSQL_ROOT_PASSWORD) $(DATABASE_MYSQL_NAME) > /tmp/dump.sql' + docker compose exec mysql sh -c 'mysqldump --databases --add-drop-database -uroot -p$(DATABASE_MYSQL_ROOT_PASSWORD) $(DATABASE_MYSQL_NAME) > /tmp/dump.sql' docker cp movary_mysql_1:/tmp/dump.sql storage/dump.sql chown $(USER_ID):$(USER_ID) storage/dump.sql @@ -107,5 +107,5 @@ app_jobs_process: make exec_app_cmd CMD="php bin/console.php jobs:process" # Shortcuts -php: exec_app_bash +php: exec_app_sh test: composer_test diff --git a/build/Dockerfile b/build/Dockerfile new file mode 100644 index 000000000..30175154c --- /dev/null +++ b/build/Dockerfile @@ -0,0 +1,73 @@ +ARG ALPINE_VERSION=3.18 +FROM alpine:${ALPINE_VERSION} as base +LABEL Maintainer="Tim de Pater " +LABEL Description="Lightweight container with Nginx 1.24 & PHP 8.2 based on Alpine Linux." +# Setup document root +WORKDIR /app + +# Install packages and remove default server definition +RUN apk add --no-cache \ + curl \ + nano \ + nginx \ + php82 \ + php82-ctype \ + php82-curl \ + php82-dom \ + php82-fileinfo \ + php82-fpm \ + php82-gd \ + php82-intl \ + php82-json \ + php82-mbstring \ + php82-mysqli \ + php82-opcache \ + php82-openssl \ + php82-pdo_mysql \ + php82-phar \ + php82-session \ + php82-simplexml \ + php82-tokenizer \ + php82-xml \ + php82-xmlreader \ + php82-xmlwriter \ + supervisor + +# build/configure nginx - http +COPY build/config/nginx.conf /etc/nginx/nginx.conf +# build/configure nginx - default server +COPY build/config/conf.d /etc/nginx/conf.d/ + +# build/configure PHP-FPM +ENV PHP_INI_DIR /etc/php82 +COPY build/config/fpm-pool.conf ${PHP_INI_DIR}/php-fpm.d/www.conf +COPY build/config/php.ini ${PHP_INI_DIR}/conf.d/custom.ini + +# build/configure supervisord +COPY build/config/supervisord.conf /etc/supervisor/conf.d/supervisord.conf + +# Make sure files/folders needed by the processes are accessable when they run under the nobody user +RUN chown -R nobody.nobody /app /run /var/lib/nginx /var/log/nginx + +# Create symlink for php +RUN ln -s /usr/bin/php82 /usr/bin/php + +# Install composer from the official image +COPY --from=composer /usr/bin/composer /usr/bin/composer + +# Switch to use a non-root user from here on +USER nobody + +# Expose the port nginx is reachable on +EXPOSE 8080 + +# Let supervisord start nginx & php-fpm +CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"] + +# configure a healthcheck to validate that everything is up&running +HEALTHCHECK --timeout=10s CMD curl --silent --fail http://127.0.0.1:8080/fpm-ping + +FROM base as development + +#FROM base as production +#COPY --chown=nobody ./ /var/www/html/ diff --git a/build/config/conf.d/default.conf b/build/config/conf.d/default.conf new file mode 100644 index 000000000..1e38f3020 --- /dev/null +++ b/build/config/conf.d/default.conf @@ -0,0 +1,57 @@ +# Default server definition +server { + listen [::]:8080 default_server; + listen 8080 default_server; + server_name _; + + sendfile off; + tcp_nodelay on; + absolute_redirect off; + + root /app/public; + index index.php index.html; + + location / { + # First attempt to serve request as file, then + # as directory, then fall back to index.php + try_files $uri $uri/ /index.php?q=$uri&$args; + } + + # Redirect server error pages to the static page /50x.html + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /var/lib/nginx/html; + } + + # Pass the PHP scripts to PHP-FPM listening on php-fpm.sock + location ~ \.php$ { + try_files $uri =404; + fastcgi_split_path_info ^(.+\.php)(/.+)$; + fastcgi_pass unix:/run/php-fpm.sock; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_param SCRIPT_NAME $fastcgi_script_name; + fastcgi_index index.php; + include fastcgi_params; + } + + # Set the cache-control headers on assets to cache for 5 days + location ~* \.(jpg|jpeg|gif|png|css|js|ico|xml)$ { + expires 5d; + } + + # Deny access to . files, for security + location ~ /\. { + log_not_found off; + deny all; + } + + # Allow fpm ping and status from localhost + location ~ ^/(fpm-status|fpm-ping)$ { + access_log off; + allow 127.0.0.1; + deny all; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + include fastcgi_params; + fastcgi_pass unix:/run/php-fpm.sock; + } +} diff --git a/build/config/fpm-pool.conf b/build/config/fpm-pool.conf new file mode 100644 index 000000000..4be20613c --- /dev/null +++ b/build/config/fpm-pool.conf @@ -0,0 +1,56 @@ +[global] +; Log to stderr +error_log = /dev/stderr + +[www] +; The address on which to accept FastCGI requests. +; Valid syntaxes are: +; 'ip.add.re.ss:port' - to listen on a TCP socket to a specific IPv4 address on +; a specific port; +; '[ip:6:addr:ess]:port' - to listen on a TCP socket to a specific IPv6 address on +; a specific port; +; 'port' - to listen on a TCP socket to all addresses +; (IPv6 and IPv4-mapped) on a specific port; +; '/path/to/unix/socket' - to listen on a unix socket. +; Note: This value is mandatory. +listen = /run/php-fpm.sock + +; Enable status page +pm.status_path = /fpm-status + +; Ondemand process manager +pm = ondemand + +; The number of child processes to be created when pm is set to 'static' and the +; maximum number of child processes when pm is set to 'dynamic' or 'ondemand'. +; This value sets the limit on the number of simultaneous requests that will be +; served. Equivalent to the ApacheMaxClients directive with mpm_prefork. +; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP +; CGI. The below defaults are based on a server without much resources. Don't +; forget to tweak pm.* to fit your needs. +; Note: Used when pm is set to 'static', 'dynamic' or 'ondemand' +; Note: This value is mandatory. +pm.max_children = 100 + +; The number of seconds after which an idle process will be killed. +; Note: Used only when pm is set to 'ondemand' +; Default Value: 10s +pm.process_idle_timeout = 10s; + +; The number of requests each child process should execute before respawning. +; This can be useful to work around memory leaks in 3rd party libraries. For +; endless request processing specify '0'. Equivalent to PHP_FCGI_MAX_REQUESTS. +; Default Value: 0 +pm.max_requests = 1000 + +; Make sure the FPM workers can reach the environment variables for configuration +clear_env = no + +; Catch output from PHP +catch_workers_output = yes + +; Remove the 'child 10 said into stderr' prefix in the log and only show the actual message +decorate_workers_output = no + +; Enable ping page to use in healthcheck +ping.path = /fpm-ping diff --git a/build/config/nginx.conf b/build/config/nginx.conf new file mode 100644 index 000000000..ba8d09a93 --- /dev/null +++ b/build/config/nginx.conf @@ -0,0 +1,45 @@ +worker_processes auto; +error_log stderr warn; +pid /run/nginx.pid; + +events { + worker_connections 1024; +} + +http { + include mime.types; + default_type application/octet-stream; + + # Define custom log format to include reponse times + log_format main_timed '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for" ' + '$request_time $upstream_response_time $pipe $upstream_cache_status'; + + access_log /dev/stdout main_timed; + error_log /dev/stderr notice; + + keepalive_timeout 65; + + # Write temporary files to /tmp so they can be created as a non-privileged user + client_body_temp_path /tmp/client_temp; + proxy_temp_path /tmp/proxy_temp_path; + fastcgi_temp_path /tmp/fastcgi_temp; + uwsgi_temp_path /tmp/uwsgi_temp; + scgi_temp_path /tmp/scgi_temp; + + # Hardening + proxy_hide_header X-Powered-By; + fastcgi_hide_header X-Powered-By; + server_tokens off; + + # Enable gzip compression by default + gzip on; + gzip_proxied any; + gzip_types text/plain application/xml text/css text/js text/xml application/x-javascript text/javascript application/json application/xml+rss; + gzip_vary on; + gzip_disable "msie6"; + + # Include server configs + include /etc/nginx/conf.d/*.conf; +} diff --git a/build/config/php.ini b/build/config/php.ini new file mode 100644 index 000000000..aec2bdbf4 --- /dev/null +++ b/build/config/php.ini @@ -0,0 +1,3 @@ +[Date] +date.timezone="UTC" +expose_php= Off diff --git a/build/config/supervisord.conf b/build/config/supervisord.conf new file mode 100644 index 000000000..2f9727ecd --- /dev/null +++ b/build/config/supervisord.conf @@ -0,0 +1,35 @@ +[supervisord] +nodaemon=true +logfile=/dev/null +logfile_maxbytes=0 +pidfile=/run/supervisord.pid + +[program:php-fpm] +command=php-fpm82 -F +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 +autorestart=false +startretries=0 + +[program:nginx] +command=nginx -g 'daemon off;' +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 +autorestart=false +startretries=0 + +[program:movary] +command=php /app/bin/console.php jobs:process +numprocs=1 +autostart=true +autorestart=true +startsecs=1 +startretries=10 +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 diff --git a/build/php/Dockerfile b/build/php/Dockerfile deleted file mode 100644 index 747606e10..000000000 --- a/build/php/Dockerfile +++ /dev/null @@ -1,15 +0,0 @@ -FROM webdevops/php-nginx:8.2-alpine AS development -ENV WEB_DOCUMENT_ROOT="/app/public" \ - PHP_DISMOD=imagick -RUN apk add --no-cache make nano -USER application -WORKDIR /app - -FROM development AS production -ARG APPLICATION_VERSION -ENV APPLICATION_VERSION=${APPLICATION_VERSION} -COPY --chown=application ./ ./ -COPY .env.production.example .env -COPY settings/supervisor/movary.conf /opt/docker/etc/supervisor.d/movary.conf -RUN composer install --no-dev -RUN php bin/console.php storage:link diff --git a/docker-compose.yml b/docker-compose.yml index b04d2e529..d3ab74b19 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,11 +4,10 @@ services: app: build: context: ./ - dockerfile: ./build/php/Dockerfile + dockerfile: build/Dockerfile target: development - user: "${USER_ID}:${USER_ID}" ports: - - "${HTTP_PORT}:80" + - "${HTTP_PORT}:8080" volumes: - ./:/app environment: diff --git a/settings/supervisor/movary.conf b/settings/supervisor/movary.conf deleted file mode 100644 index 47dbd8a1d..000000000 --- a/settings/supervisor/movary.conf +++ /dev/null @@ -1,12 +0,0 @@ -[program:movary] -command=/usr/local/bin/php /app/bin/console.php jobs:process -numprocs=1 -user=application -autostart=true -autorestart=true -startsecs=1 -startretries=10 -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 From 78e6e4ffd3344278d52f4c63b180767562c0f36f Mon Sep 17 00:00:00 2001 From: Lee Peuker Date: Sun, 5 Nov 2023 18:07:19 +0100 Subject: [PATCH 2/3] Revert some test changes --- Makefile | 6 +++--- build/config/conf.d/default.conf | 4 ++-- docker-compose.yml | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 3fdb08fb6..53d9910aa 100644 --- a/Makefile +++ b/Makefile @@ -25,10 +25,10 @@ logs: build: docker compose build --no-cache make up - #make db_mysql_create_database + make db_mysql_create_database make composer_install -# make app_database_migrate -# make exec_app_cmd CMD="php bin/console.php storage:link" + make app_database_migrate + make exec_app_cmd CMD="php bin/console.php storage:link" # Container interaction ####################### diff --git a/build/config/conf.d/default.conf b/build/config/conf.d/default.conf index 1e38f3020..bfb2703eb 100644 --- a/build/config/conf.d/default.conf +++ b/build/config/conf.d/default.conf @@ -1,7 +1,7 @@ # Default server definition server { - listen [::]:8080 default_server; - listen 8080 default_server; + listen [::]:80 default_server; + listen 80 default_server; server_name _; sendfile off; diff --git a/docker-compose.yml b/docker-compose.yml index d3ab74b19..617e3e51a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,10 +4,10 @@ services: app: build: context: ./ - dockerfile: build/Dockerfile + dockerfile: ./build/Dockerfile target: development ports: - - "${HTTP_PORT}:8080" + - "${HTTP_PORT}:80" volumes: - ./:/app environment: From b1dd4e80e04b6ebd9d5bb93261adbb014b4264d8 Mon Sep 17 00:00:00 2001 From: Lee Peuker Date: Sun, 5 Nov 2023 18:43:36 +0100 Subject: [PATCH 3/3] Formatting dockerfile --- build/Dockerfile | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/build/Dockerfile b/build/Dockerfile index 30175154c..13ee79c36 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -1,11 +1,10 @@ -ARG ALPINE_VERSION=3.18 -FROM alpine:${ALPINE_VERSION} as base -LABEL Maintainer="Tim de Pater " -LABEL Description="Lightweight container with Nginx 1.24 & PHP 8.2 based on Alpine Linux." -# Setup document root +############## +# Base image # +############## +FROM alpine:3.18 as base + WORKDIR /app -# Install packages and remove default server definition RUN apk add --no-cache \ curl \ nano \ @@ -33,17 +32,16 @@ RUN apk add --no-cache \ php82-xmlwriter \ supervisor -# build/configure nginx - http +# Configure nginx COPY build/config/nginx.conf /etc/nginx/nginx.conf -# build/configure nginx - default server COPY build/config/conf.d /etc/nginx/conf.d/ -# build/configure PHP-FPM +# Configure PHP-FPM ENV PHP_INI_DIR /etc/php82 COPY build/config/fpm-pool.conf ${PHP_INI_DIR}/php-fpm.d/www.conf COPY build/config/php.ini ${PHP_INI_DIR}/conf.d/custom.ini -# build/configure supervisord +# Configure supervisord COPY build/config/supervisord.conf /etc/supervisor/conf.d/supervisord.conf # Make sure files/folders needed by the processes are accessable when they run under the nobody user @@ -64,10 +62,15 @@ EXPOSE 8080 # Let supervisord start nginx & php-fpm CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"] -# configure a healthcheck to validate that everything is up&running +# Configure a healthcheck to validate that everything is up & running HEALTHCHECK --timeout=10s CMD curl --silent --fail http://127.0.0.1:8080/fpm-ping +##################### +# Development image # +##################### FROM base as development -#FROM base as production -#COPY --chown=nobody ./ /var/www/html/ +#################### +# Production image # +#################### +FROM base as production