Skip to content

Instantly share code, notes, and snippets.

@tacocode-dev
Forked from chris-cmsoft/.dockerignore
Created September 5, 2021 00:34
Show Gist options
  • Save tacocode-dev/1c2ff23d4a0d86f3e625ca56ebb9344e to your computer and use it in GitHub Desktop.
Save tacocode-dev/1c2ff23d4a0d86f3e625ca56ebb9344e to your computer and use it in GitHub Desktop.
TLDR - Laravel In Kubernetes Part 2
/vendor
/node_modules
version: '3'
services:
laravel.fpm:
build:
context: .
target: fpm_server
image: laravel-in-kubernetes/fpm_server
environment:
APP_DEBUG: "true"
volumes:
- '.:/opt/apps/laravel-in-kubernetes'
networks:
- laravel-in-kubernetes
laravel.web:
build:
context: .
target: web_server
image: laravel-in-kubernetes/web_server
ports:
- '8080:80'
environment:
FPM_HOST: "laravel.fpm:9000"
volumes:
- './public:/opt/apps/laravel-in-kubernetes/public'
networks:
- laravel-in-kubernetes
laravel.cron:
build:
context: .
target: cron
image: laravel-in-kubernetes/cron
volumes:
- '.:/opt/apps/laravel-in-kubernetes'
networks:
- laravel-in-kubernetes
mysql:
image: 'mysql:8.0'
ports:
- '${FORWARD_DB_PORT:-3306}:3306'
environment:
MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}'
MYSQL_DATABASE: '${DB_DATABASE}'
MYSQL_USER: '${DB_USERNAME}'
MYSQL_PASSWORD: '${DB_PASSWORD}'
MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
volumes:
- 'laravel-in-kubernetes-mysql:/var/lib/mysql'
networks:
- laravel-in-kubernetes
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-p${DB_PASSWORD}"]
retries: 3
timeout: 5s
networks:
laravel-in-kubernetes:
volumes:
laravel-in-kubernetes-mysql:
FROM composer:2.1 as code_base
# First, create the application directory
RUN mkdir -p /opt/apps/laravel-in-kubernetes
# Set the working directory
WORKDIR /opt/apps/laravel-in-kubernetes
# Create a composer group and user,
# and create a home directory for it to keep the rest of the image safe,
# and not accidentally run malicious scripts
RUN addgroup -S composer \
&& adduser -S composer -G composer \
&& chown -R composer /opt/apps/laravel-in-kubernetes
# Switch to the composer user before running installs.
USER composer
# Copy in dependency files
COPY --chown=composer composer.json composer.lock ./
# Install all the dependencies without running any installation scripts.
# We skip scripts, as the code base hasn't been copied in yet and script will likely fail,
# as artisan isn't in the container yet.
# This also helps us to cache previous runs and layers.
# As long as comoser.json and composer.lock doesn't change the install will be cached.
RUN composer install --no-dev --no-scripts --no-autoloader --prefer-dist
# Copy in the actual source code so we can run the installation scripts we need
COPY --chown=composer . .
# Install all the dependencies running installation scripts as well
RUN composer install --no-dev --prefer-dist
##############
# Create a CLI layer to run migrations, crons, queues etc.
##############
FROM php:8.0-alpine as cli
WORKDIR /opt/apps/laravel-in-kubernetes
# Install some requirements into our image, used to compile our PHP extensions,
# as well as install all the extensions themselves.
#
# You can see a list of required extensions here: https://laravel.com/docs/8.x/deployment#server-requirements
RUN apk add --virtual build-dependencies --no-cache openssl ca-certificates libxml2-dev oniguruma-dev && \
docker-php-ext-install -j$(nproc) pdo pdo_mysql bcmath ctype fileinfo dom tokenizer mbstring tokenizer && \
apk del build-dependencies
# Copy in the code base from our initial code_base build
COPY --from=code_base /opt/apps/laravel-in-kubernetes /opt/apps/laravel-in-kubernetes
##############
# Create a FPM layer to process PHP requests
##############
FROM php:8.0-fpm-alpine as fpm_server
WORKDIR /opt/apps/laravel-in-kubernetes
# Install PHP extensions
RUN apk add --virtual build-dependencies --no-cache openssl ca-certificates libxml2-dev oniguruma-dev && \
docker-php-ext-install -j$(nproc) pdo pdo_mysql bcmath ctype fileinfo dom tokenizer mbstring tokenizer && \
apk del build-dependencies
# Copy code base
COPY --from=code_base /opt/apps/laravel-in-kubernetes /opt/apps/laravel-in-kubernetes
##############
# Create a Nginx layer to process serve static content, and proxy PHP requests
##############
FROM nginx:1.20-alpine as web_server
WORKDIR /opt/apps/laravel-in-kubernetes
Install nginx config
COPY nginx.conf.template /etc/nginx/templates/default.conf.template
# Copy in ONLY the public directory for the application.
# This is where all the static assets will live, which nginx will serve for us.
# Any PHP requests will be passed down to FPM
COPY --from=code_base /opt/apps/laravel-in-kubernetes/public /opt/apps/laravel-in-kubernetes/public
CMD ["nginx", "-c", "/etc/nginx/nginx.conf"]
##############
# Create a Cron layer to run Laravel schedule
##############
FROM cli as cron
WORKDIR /opt/apps/laravel-in-kubernetes
# Create a laravel.cron file with Laravel cron settings and import into crontab,
RUN touch laravel.cron && \
echo "* * * * * cd /opt/apps/laravel-in-kubernetes && php artisan schedule:run" >> laravel.cron && \
crontab laravel.cron
# Run crond as the primary command in the forground
CMD ["crond", "-l", "2", "-f"]
##############
# Set the CLI layer as the default for the container
##############
FROM cli
server {
listen 80 default_server;
listen [::]:80 default_server;
# We need to set the root for our sevrer,
# so any static file requests gets loaded from the correct path
root /opt/apps/laravel-in-kubernetes/public;
index index.php index.html index.htm index.nginx-debian.html;
# _ makes sure that nginx does not try to map requests to a specific hostname
# This allows us to specify the urls to our application as infrastructure changes,
# without needing to change the application
server_name _;
# At the root location,
# we first check if there are any static files at the location, and serve those,
# If not, we check whether there is an indexable folder which can be served,
# Otherwise we forward the request to the PHP server
location / {
# Using try_files here is quite important as a security concideration
# to prevent injecting PHP code as static assets,
# and then executing them via a URL.
# See https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/#passing-uncontrolled-requests-to-php
try_files $uri $uri/ /index.php?$query_string;
}
# Some static assets are loaded on every page load,
# and logging these turns into a lot of useless logs.
# If you would prefer to see these requests for catching 404's etc.
# Feel free to remove them
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
# When a 404 is returned, we want to display our applications 404 page,
# so we redirect it to index.php to load the correct page
error_page 404 /index.php;
# Whenever we receive a PHP url, or our root location block gets to serving through fpm,
# we want to pass the request to FPM for processing
location ~ \.php$ {
#NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
include fastcgi_params;
fastcgi_intercept_errors on;
fastcgi_pass ${FPM_HOST};
fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
}
location ~ /\.ht {
deny all;
}
location ~ /\.(?!well-known).* {
deny all;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment