Skip to content

Instantly share code, notes, and snippets.

@owldesign
Last active October 10, 2025 02:54
Show Gist options
  • Select an option

  • Save owldesign/538f3047474de4a502765362dfbcd808 to your computer and use it in GitHub Desktop.

Select an option

Save owldesign/538f3047474de4a502765362dfbcd808 to your computer and use it in GitHub Desktop.
Craft CMS with Docker instructions
#Coolify env (Optional)
CRAFT_ENVIRONMENT=production
CRAFT_APP_ID=
CRAFT_SECURITY_KEY=
CRAFT_DB_DRIVER="mysql"
CRAFT_DB_SERVER="db"
CRAFT_DB_PORT="3306"
CRAFT_DB_DATABASE="db"
CRAFT_DB_USER="db"
CRAFT_DB_PASSWORD="db"
CRAFT_DB_SCHEMA=
CRAFT_DB_TABLE_PREFIX=
PRIMARY_SITE_URL="https://someproduction.url"
services:
db:
image: mysql
environment:
MYSQL_DATABASE: db # Database name
MYSQL_USER: db # Database user
MYSQL_PASSWORD: db # Database password
MYSQL_ROOT_PASSWORD: root # Root password (credentials only available in the container)
volumes:
- db_data:/var/lib/mysql # Maps the 'db_data' named volume to MySQL's data directory
healthcheck: # Configures a health check for the database
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 1s
timeout: 3s
retries: 10
web:
build: # Specifies how to build the Docker image
context: .
dockerfile: ./.coolify/Dockerfile # Specifies the path to the Dockerfile
args: # Passes build arguments to the Dockerfile
- php_version=8.2 # Sets the PHP version
- node_version=22 # Sets the Node.js version
depends_on:
db:
condition: service_healthy # Ensures the 'web' service starts only after the 'db' service is healthy
volumes:
- assets_data:/app/web/assets # Maps the 'assets_data' named volume to asset directory
volumes:
db_data: # Defines the 'db_data' volume for persistent database storage (database is not deleted during deploy)
assets_data: # Defines the 'assets_data' volume for persistent asset storage (assets get not deleted during deploy)
ARG php_version=8.3
ARG node_version=22
### Stage 1: Node Build Environment
FROM node:${node_version}-alpine as nodebuilder
WORKDIR /app
COPY package.json package-lock.json ./
# Install Node.js dependencies using npm ci for clean and consistent installs.
RUN npm ci
COPY . .
# Build the frontend assets using the build script defined in package.json.
RUN npm run build
### Stage 2: CraftCMS + PHP
FROM craftcms/nginx:${php_version}
USER root
# Install Composer: Copy the Composer executable from the official Composer image.
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# Install system tools like git, unzip, bash, and vim using apk (Alpine Package Keeper).
# --no-cache avoids caching package lists, reducing image size.
# mariadb-connector and mysql-client are needed to use mysqldump in the web container.
RUN apk add --no-cache git unzip bash vim mariadb-connector-c mysql-client
WORKDIR /app
# Copy the composer.json and composer.lock files to the working directory.
COPY composer.json composer.lock ./
# Install PHP dependencies using Composer, with --no-interaction, --no-dev, and --optimize-autoloader flags.
# --no-interaction: Prevents Composer from prompting for user input.
# --no-dev: Skips installing development dependencies.
# --optimize-autoloader: Improves autoloader performance.
RUN composer install --no-interaction --no-dev --optimize-autoloader
# Copy the compiled frontend assets from the nodebuilder stage to the /app/web/dist directory.
COPY --from=nodebuilder /app/web/dist /app/web/dist
# Copy the rest of the project files (backend code) into the container.
COPY . .
# Set permissions for Craft CMS directories and .env file.
# Create the storage, cpresources, and assets directories if they don't exist.
# Change ownership of config, storage, cpresources, assets, and .env to www-data.
# Set file permissions to 775 (read, write, execute for owner and group, read and execute for others).
RUN mkdir -p /app/storage /app/web/cpresources /app/web/assets \
&& chown -R www-data:www-data /app/config /app/storage /app/web/cpresources /app/web/assets /app/.env \
&& chmod -R 775 /app/config /app/storage /app/web/cpresources /app/web/assets /app/.env
# Switch back to the www-data user to run the Nginx web server.
USER www-data
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment