diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b1a3ccc..78a9c8e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -209,7 +209,7 @@ jobs: id: meta uses: docker/metadata-action@v4 with: - images: alkrauss48/simple-slides-sail + images: alkrauss48/simple-slides-laravel tags: | type=ref,prefix=dev-,event=branch type=semver,pattern={{version}} @@ -230,7 +230,7 @@ jobs: uses: docker/build-push-action@v4 with: context: . - file: docker/sail-prod/Dockerfile + file: docker/app/Dockerfile push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 8deb7a7..11239b9 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -1,34 +1,10 @@ services: - # TODO: Get nginx + php docker setup working for prod, instead of sail - # - # nginx: - # build: - # context: . - # dockerfile: docker/php/Dockerfile - # target: nginx-image - # restart: unless-stopped - # ports: - # - 80:80 - # depends_on: - # - laravel - # - # laravel: - # build: - # context: . - # dockerfile: docker/php/Dockerfile - # target: php-image - # env_file: - # - .env.prod - # depends_on: - # - pgsql - # - redis - laravel: build: - context: . - dockerfile: docker/sail-prod/Dockerfile + context: . + dockerfile: docker/app/Dockerfile env_file: - - .env.prod + - .env.prod ports: - 80:80 depends_on: diff --git a/docker/app/Dockerfile b/docker/app/Dockerfile new file mode 100644 index 0000000..e6a0af8 --- /dev/null +++ b/docker/app/Dockerfile @@ -0,0 +1,74 @@ +ARG PHP_VERSION=8.2 +ARG INSTALL_BCMATH=true +ARG INSTALL_CALENDAR=false +ARG INSTALL_EXIF=true +ARG INSTALL_GD=true +ARG INSTALL_IMAGICK=true +ARG INSTALL_MOSQUITTO=false +ARG INSTALL_MYSQL=false +ARG INSTALL_OPCACHE=true +ARG INSTALL_PCNTL=true +ARG INSTALL_PGSQL=true +ARG INSTALL_REDIS=true +ARG INSTALL_SQLSRV=false +ARG INSTALL_XDEBUG=false +ARG INSTALL_ZIP=true +ARG INSTALL_INTL=true + +# Backend build +FROM ghcr.io/clevyr/php:$PHP_VERSION-base as php-builder +WORKDIR /app + +COPY composer.json composer.lock ./ +RUN composer install \ + --ignore-platform-reqs \ + --no-autoloader \ + --no-interaction \ + --no-progress \ + --no-suggest + +COPY . . +RUN set -x \ + && export TELESCOPE_ENABLED=false \ + && composer dump-autoload \ + --classmap-authoritative \ + --no-interaction \ + && php artisan vendor:publish --tag=public + + +# Frontend build +FROM node:18-alpine as node-builder +WORKDIR /app + +COPY package.json package-lock.json ./ +RUN npm ci + +COPY --from=php-builder /app . +ARG NODE_ENV=production +RUN npm run build + + +# Local image +FROM ghcr.io/clevyr/php:$PHP_VERSION-onbuild as local-image +WORKDIR /app + +ENV PHP_UPLOAD_MAX_FILESIZE=64m +ENV PHP_POST_MAX_SIZE=64m + +# Install libraries for laravel-medialibrary +RUN set -x \ + && apk add --no-cache \ + ffmpeg \ + jpegoptim + +COPY --chown=root docker/app/rootfs / +RUN crontab /etc/cron.d/scheduler + +CMD ["s6-svscan", "/etc/s6/app"] + + +# Deployed image +FROM local-image + +COPY --from=php-builder --chown=82:82 /app . +COPY --from=node-builder --chown=82:82 /app/public public/ diff --git a/docker/app/rootfs/entrypoint b/docker/app/rootfs/entrypoint new file mode 100755 index 0000000..3c50c5f --- /dev/null +++ b/docker/app/rootfs/entrypoint @@ -0,0 +1,34 @@ +#!/bin/sh +set -ex + +cd /app + +( + if [ -f .env ]; then + source .env + fi + + if [ "$APP_ENV" != "local" ]; then + php artisan config:cache + else + composer install --ignore-platform-reqs --no-interaction --no-progress + php artisan config:clear + php artisan vendor:publish --tag=public + fi + + if [ -L public/storage ]; then + rm public/storage + fi + ln -s ../storage/app/public public/storage + + php artisan vendor:publish --force --tag=telescope-assets --tag=horizon-assets + + if [ "$DB_FRESH_ON_START" = "true" ]; then + php artisan migrate:fresh + php artisan db:seed + else + php artisan migrate --force + fi +) + +exec php-fpm diff --git a/docker/app/rootfs/etc/cron.d/scheduler b/docker/app/rootfs/etc/cron.d/scheduler new file mode 100644 index 0000000..9bd960b --- /dev/null +++ b/docker/app/rootfs/etc/cron.d/scheduler @@ -0,0 +1 @@ +* * * * * s6-setuidgid "${PUID:-www-data}" php /app/artisan schedule:run -n | grep -v 'No scheduled commands are ready to run.' diff --git a/docker/app/rootfs/etc/nginx/conf.d/default.conf b/docker/app/rootfs/etc/nginx/conf.d/default.conf new file mode 100644 index 0000000..b04703d --- /dev/null +++ b/docker/app/rootfs/etc/nginx/conf.d/default.conf @@ -0,0 +1,53 @@ +server { + listen 80; + listen [::]:80 default ipv6only=on; + + server_name _; + + access_log off; + + root /app/public; + index index.php index.html index.htm; + + client_max_body_size 64m; + + location / { + try_files $uri $uri/ /index.php?$query_string; + } + + location ~* \.(?:css(\.map)?|js(\.map)?|jpe?g|png|gif|ico|cur|heic|webp|tiff?|mp3|m4a|aac|ogg|midi?|wav|mp4|mov|webm|mpe?g|avi|ogv|flv|wmv)$ { + try_files $uri $uri/ /index.php?$query_string; + expires 7d; + } + + location ~* \.(?:svgz?|ttf|ttc|otf|eot|woff2?)$ { + try_files $uri $uri/ /index.php?$query_string; + add_header Access-Control-Allow-Origin "*"; + expires 7d; + } + + location ~ [^/]\.php(/|$) { + fastcgi_pass 127.0.0.1:9000; + + # regex to split $uri to $fastcgi_script_name and $fastcgi_path + fastcgi_split_path_info ^(.+\.php)(/.+)$; + + # Check that the PHP script exists before passing it + try_files $fastcgi_script_name =404; + + # Bypass the fact that try_files resets $fastcgi_path_info + # see: http://trac.nginx.org/nginx/ticket/321 + set $path_info $fastcgi_path_info; + fastcgi_param PATH_INFO $path_info; + + fastcgi_index index.php; + + fastcgi_param SCRIPT_FILENAME /app/public/index.php; + + include fastcgi.conf; + } + + location ~* \.(htaccess|htpasswd) { + deny all; + } +} diff --git a/docker/app/rootfs/etc/s6/app/nginx/down-signal b/docker/app/rootfs/etc/s6/app/nginx/down-signal new file mode 100644 index 0000000..c91fe26 --- /dev/null +++ b/docker/app/rootfs/etc/s6/app/nginx/down-signal @@ -0,0 +1 @@ +SIGQUIT diff --git a/docker/app/rootfs/etc/s6/app/nginx/run b/docker/app/rootfs/etc/s6/app/nginx/run new file mode 100755 index 0000000..3ea754c --- /dev/null +++ b/docker/app/rootfs/etc/s6/app/nginx/run @@ -0,0 +1,3 @@ +#!/bin/sh + +exec nginx -g 'daemon off;' diff --git a/docker/app/rootfs/etc/s6/app/php-fpm/down-signal b/docker/app/rootfs/etc/s6/app/php-fpm/down-signal new file mode 100644 index 0000000..c91fe26 --- /dev/null +++ b/docker/app/rootfs/etc/s6/app/php-fpm/down-signal @@ -0,0 +1 @@ +SIGQUIT diff --git a/docker/app/rootfs/etc/s6/app/php-fpm/run b/docker/app/rootfs/etc/s6/app/php-fpm/run new file mode 100755 index 0000000..0a85d64 --- /dev/null +++ b/docker/app/rootfs/etc/s6/app/php-fpm/run @@ -0,0 +1,3 @@ +#!/bin/sh + +exec /entrypoint diff --git a/docker/app/rootfs/etc/s6/worker/cron/run b/docker/app/rootfs/etc/s6/worker/cron/run new file mode 100755 index 0000000..f8c7615 --- /dev/null +++ b/docker/app/rootfs/etc/s6/worker/cron/run @@ -0,0 +1,4 @@ +#!/bin/sh +set -x + +exec crond -f diff --git a/docker/app/rootfs/etc/s6/worker/queue-runner/run b/docker/app/rootfs/etc/s6/worker/queue-runner/run new file mode 100755 index 0000000..ffc90c6 --- /dev/null +++ b/docker/app/rootfs/etc/s6/worker/queue-runner/run @@ -0,0 +1,4 @@ +#!/bin/sh +set -x + +exec s6-setuidgid "${PUID:-www-data}" php /app/artisan queue:work -n --delay=90 --tries=3 diff --git a/docker/app/rootfs/health-check b/docker/app/rootfs/health-check new file mode 100755 index 0000000..33f936e --- /dev/null +++ b/docker/app/rootfs/health-check @@ -0,0 +1,11 @@ +#!/bin/sh + +HEALTH_CHECK_IP="${1:-127.0.0.1}" + +REDIRECT_STATUS=true \ + SCRIPT_NAME=/ping \ + SCRIPT_FILENAME=/ping \ + REQUEST_METHOD=GET \ + cgi-fcgi -bind -connect "$HEALTH_CHECK_IP:9000" \ + | grep pong +exit $? diff --git a/docker/app/rootfs/usr/local/etc/php/conf.d/99-docker-php-ext-xdebug-config.ini b/docker/app/rootfs/usr/local/etc/php/conf.d/99-docker-php-ext-xdebug-config.ini new file mode 100644 index 0000000..fe50679 --- /dev/null +++ b/docker/app/rootfs/usr/local/etc/php/conf.d/99-docker-php-ext-xdebug-config.ini @@ -0,0 +1,6 @@ +[xdebug] +xdebug.remote_autostart = 0 +xdebug.remote_enable = 1 +xdebug.remote_host = "host.docker.internal" +xdebug.remote_port = 9000 +xdebug.remote_profiler_enable_trigger = 1 diff --git a/docker/nginx/Dockerfile b/docker/nginx/Dockerfile deleted file mode 100644 index 77ff762..0000000 --- a/docker/nginx/Dockerfile +++ /dev/null @@ -1,18 +0,0 @@ -# Frontend build -FROM node:18-alpine as node-builder -WORKDIR /app - -COPY package.json package-lock.json ./ -RUN npm ci - -COPY . . -ARG NODE_ENV=production -RUN npm run build - -# Final Image -FROM nginx:stable-alpine -WORKDIR /var/www/html - -COPY ./docker/nginx/nginx.conf /etc/nginx -COPY . . -COPY --from=node-builder --chown=82:82 /app/public public diff --git a/docker/nginx/conf.d/app.conf b/docker/nginx/conf.d/app.conf deleted file mode 100644 index 14765ba..0000000 --- a/docker/nginx/conf.d/app.conf +++ /dev/null @@ -1,47 +0,0 @@ -server { - listen 80; - index index.php index.html; - error_log /var/log/nginx/error.log; - access_log /var/log/nginx/access.log; - root /var/www/public; - - add_header X-Frame-Options "SAMEORIGIN"; - add_header X-Content-Type-Options "nosniff"; - - index index.php; - - charset utf-8; - - location / { - try_files $uri $uri/ /index.php?$query_string; - } - - location = /favicon.ico { access_log off; log_not_found off; } - location = /robots.txt { access_log off; log_not_found off; } - - error_page 404 /index.php; - - location ~ \.php$ { - fastcgi_pass laravel:9000; - fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; - include fastcgi_params; - } - - location ~ /\.(?!well-known).* { - deny all; - } - - # location ~ \.php$ { - # try_files $uri =404; - # fastcgi_split_path_info ^(.+\.php)(/.+)$; - # fastcgi_pass laravel:9000; - # fastcgi_index index.php; - # include fastcgi_params; - # fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; - # fastcgi_param PATH_INFO $fastcgi_path_info; - # } - # location / { - # try_files $uri $uri/ /index.php?$query_string; - # gzip_static on; - # } -} diff --git a/docker/nginx/nginx.conf/fastcgi.conf b/docker/nginx/nginx.conf/fastcgi.conf deleted file mode 100644 index f74064d..0000000 --- a/docker/nginx/nginx.conf/fastcgi.conf +++ /dev/null @@ -1,21 +0,0 @@ -fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; -fastcgi_param QUERY_STRING $query_string; -fastcgi_param REQUEST_METHOD $request_method; -fastcgi_param CONTENT_TYPE $content_type; -fastcgi_param CONTENT_LENGTH $content_length; -fastcgi_param SCRIPT_NAME $fastcgi_script_name; -fastcgi_param REQUEST_URI $request_uri; -fastcgi_param DOCUMENT_URI $document_uri; -fastcgi_param DOCUMENT_ROOT $document_root; -fastcgi_param SERVER_PROTOCOL $server_protocol; -fastcgi_param GATEWAY_INTERFACE CGI/1.1; -fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; -fastcgi_param REMOTE_ADDR $remote_addr; -fastcgi_param REMOTE_PORT $remote_port; -fastcgi_param SERVER_ADDR $server_addr; -fastcgi_param SERVER_PORT $server_port; -fastcgi_param SERVER_NAME $server_name; - -fastcgi_index index.php; - -fastcgi_param REDIRECT_STATUS 200; diff --git a/docker/nginx/nginx.conf/fastcgi_params b/docker/nginx/nginx.conf/fastcgi_params deleted file mode 100644 index b69ae25..0000000 --- a/docker/nginx/nginx.conf/fastcgi_params +++ /dev/null @@ -1,27 +0,0 @@ -fastcgi_param QUERY_STRING $query_string; -fastcgi_param REQUEST_METHOD $request_method; -fastcgi_param CONTENT_TYPE $content_type; -fastcgi_param CONTENT_LENGTH $content_length; - -fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; -fastcgi_param SCRIPT_NAME $fastcgi_script_name; -fastcgi_param PATH_INFO $fastcgi_path_info; -fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info; -fastcgi_param REQUEST_URI $request_uri; -fastcgi_param DOCUMENT_URI $document_uri; -fastcgi_param DOCUMENT_ROOT $document_root; -fastcgi_param SERVER_PROTOCOL $server_protocol; - -fastcgi_param GATEWAY_INTERFACE CGI/1.1; -fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; - -fastcgi_param REMOTE_ADDR $remote_addr; -fastcgi_param REMOTE_PORT $remote_port; -fastcgi_param SERVER_ADDR $server_addr; -fastcgi_param SERVER_PORT $server_port; -fastcgi_param SERVER_NAME $server_name; - -fastcgi_param HTTPS $https; - -# PHP only, required if PHP was built with --enable-force-cgi-redirect -fastcgi_param REDIRECT_STATUS 200; diff --git a/docker/nginx/nginx.conf/mime.types b/docker/nginx/nginx.conf/mime.types deleted file mode 100644 index 25ae94e..0000000 --- a/docker/nginx/nginx.conf/mime.types +++ /dev/null @@ -1,48 +0,0 @@ -types { - text/html html htm shtml; - text/css css; - text/xml xml rss; - image/gif gif; - image/jpeg jpeg jpg; - application/x-javascript js; - text/plain txt; - text/x-component htc; - text/mathml mml; - image/png png; - image/x-icon ico; - image/x-jng jng; - image/vnd.wap.wbmp wbmp; - application/java-archive jar war ear; - application/mac-binhex40 hqx; - application/pdf pdf; - application/x-cocoa cco; - application/x-java-archive-diff jardiff; - application/x-java-jnlp-file jnlp; - application/x-makeself run; - application/x-perl pl pm; - application/x-pilot prc pdb; - application/x-rar-compressed rar; - application/x-redhat-package-manager rpm; - application/x-sea sea; - application/x-shockwave-flash swf; - application/x-stuffit sit; - application/x-tcl tcl tk; - application/x-x509-ca-cert der pem crt; - application/x-xpinstall xpi; - application/zip zip; - application/octet-stream deb; - application/octet-stream bin exe dll; - application/octet-stream dmg; - application/octet-stream eot; - application/octet-stream iso img; - application/octet-stream msi msp msm; - audio/mpeg mp3; - audio/x-realaudio ra; - video/mpeg mpeg mpg; - video/quicktime mov; - video/x-flv flv; - video/x-msvideo avi; - video/x-ms-wmv wmv; - video/x-ms-asf asx asf; - video/x-mng mng; -} diff --git a/docker/nginx/nginx.conf/nginx.conf b/docker/nginx/nginx.conf/nginx.conf deleted file mode 100644 index 69902bd..0000000 --- a/docker/nginx/nginx.conf/nginx.conf +++ /dev/null @@ -1,26 +0,0 @@ -user nginx nginx; -worker_processes 5; -error_log /var/log/nginx/error.log; -pid /run/nginx/nginx.pid; -worker_rlimit_nofile 8192; - -events { - worker_connections 4096; -} - -http { - include mime.types; - include fastcgi.conf; - - index index.php index.html; - - default_type application/octet-stream; - - log_format main '$remote_addr "$http_x_forwarded_for" - $remote_user [$time_local] $status "$request"'; - access_log /var/log/nginx/access.log main; - - sendfile on; - tcp_nopush on; - - include sites-enabled/*; -} diff --git a/docker/nginx/nginx.conf/sites-enabled/laravel b/docker/nginx/nginx.conf/sites-enabled/laravel deleted file mode 100644 index ed11851..0000000 --- a/docker/nginx/nginx.conf/sites-enabled/laravel +++ /dev/null @@ -1,29 +0,0 @@ -server { - listen 80; - listen [::]:80; - - root /var/www/html/public; - - add_header X-Frame-Options "SAMEORIGIN"; - add_header X-Content-Type-Options "nosniff"; - - index index.php index.html; - - charset utf-8; - - error_page 404 /index.php; - - location / {try_files $uri $uri/ /index.php?$query_string;} - location = /favicon.ico { access_log off; log_not_found off; } - location = /robots.txt { access_log off; log_not_found off; } - - location ~ \.php$ { - fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; - include fastcgi_params; - fastcgi_pass laravel:9000; - } - - location ~ /\.(?!well-known).* { - deny all; - } -} diff --git a/docker/php/Dockerfile b/docker/php/Dockerfile deleted file mode 100644 index b43d4c0..0000000 --- a/docker/php/Dockerfile +++ /dev/null @@ -1,114 +0,0 @@ -# PHP Builder -FROM php:8.2-fpm as php-builder - -# Set working directory -WORKDIR /var/www/html - -# Install dependencies -RUN apt-get update && apt-get install -y \ - build-essential \ - libpng-dev \ - libjpeg62-turbo-dev \ - libfreetype6-dev \ - locales \ - zip \ - jpegoptim optipng pngquant gifsicle \ - vim \ - unzip \ - git \ - curl \ - libonig-dev \ - libxml2-dev \ - zlib1g-dev \ - libpq-dev \ - libzip-dev - -# compile native PHP packages -RUN docker-php-ext-install \ - gd \ - pcntl \ - bcmath \ - mysqli \ - pdo pdo_pgsql pgsql - -# configure packages -RUN docker-php-ext-configure gd --with-freetype --with-jpeg - -# install additional packages from PECL -RUN pecl install zip && docker-php-ext-enable zip \ - && pecl install igbinary && docker-php-ext-enable igbinary - -RUN pecl install redis && docker-php-ext-enable redis - -# RUN docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql \ -# && docker-php-ext-install pdo pdo_pgsql pgsql zip bcmath gd - -# Clear cache -RUN apt-get clean && rm -rf /var/lib/apt/lists/* - -# Install extensions -# RUN docker-php-ext-install pdo_mysql zip exif pcntl -# RUN docker-php-ext-configure gd --with-gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ --with-png-dir=/usr/include/ -# RUN docker-php-ext-install gd - -# Install composer -RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer - -# Add user for laravel application -RUN groupadd -g 1000 www -RUN useradd -u 1000 -ms /bin/bash -g www www - -# Copy composer.lock and composer.json -COPY composer.lock composer.json /var/www/html - -RUN composer install \ - --ignore-platform-reqs \ - --no-autoloader \ - --no-interaction \ - --no-progress - -# Copy existing application directory contents -COPY . /var/www/html - -RUN set -x \ - && composer dump-autoload \ - --classmap-authoritative \ - --no-interaction - -# Copy existing application directory permissions -COPY ./docker/php/local.ini /usr/local/etc/php/conf.d/local.ini - -RUN chmod -R a+w storage - -# Change current user to www -USER www - -### END PHP BUILDER - -# Frontend build -FROM node:18-alpine as node-builder -WORKDIR /app - -COPY package.json package-lock.json ./ -RUN npm ci - -COPY --from=php-builder /var/www/html . -ARG NODE_ENV=production -RUN npm run build - -# Final PHP Image -FROM php-builder as php-image - -COPY --from=node-builder --chown=82:82 /app/public /var/www/html/public/ - -# Start php-fpm server -CMD ["php-fpm"] - -# Final Nginx Image -FROM nginx:stable-alpine as nginx-image -WORKDIR /var/www/html - -RUN mkdir -p /run/nginx -COPY --from=php-builder --chown=82:82 /var/www/html/public public -COPY --from=node-builder --chown=82:82 /app/public public -COPY ./docker/nginx/nginx.conf /etc/nginx diff --git a/docker/php/local.ini b/docker/php/local.ini deleted file mode 100644 index 94b4005..0000000 --- a/docker/php/local.ini +++ /dev/null @@ -1,2 +0,0 @@ -upload_max_filesize=10M -post_max_size=10M