fix: isolate app_network with unique name per project

Use ${REVERSE_DOMAIN}-app_network instead of shared app_network
to prevent Docker DNS collisions when multiple projects have
services with the same name (e.g., redis, db).
master
Guillermo Pages 2 months ago
commit 9745cb1a6c

BIN
.DS_Store vendored

Binary file not shown.

@ -0,0 +1,10 @@
sn48:
vault:
hydrate:
branches:
- master
copy_files:
- docker/filebrowser/settings.json
deploy: 2

@ -0,0 +1,147 @@
kind: pipeline
type: docker
name: default
trigger:
branch:
- master
steps:
- name: debug-secrets
image: alpine
environment:
VAULT_API_URL:
from_secret: VAULT_API_URL
commands:
- 'echo "Docker Registry URL: $${VAULT_API_URL}"'
when:
event:
- push
- tag
# Make the image available for next step
- name: cron
image: plugins/docker
settings:
dockerfile: docker/wp-cron/Dockerfile
context: .
registry: registry.sn48.zivili.ch
repo: registry.sn48.zivili.ch/meow/wp-cron
tags:
- "amd64-1.0.0"
- "latest"
username:
from_secret: PORTUS_USER
password:
from_secret: PORTUS_PASSWORD
debug: true
launch_debug: true
# make sure to replace image with same tag
force_tag: true
when:
event:
- push
- tag
- name: deploy
image: registry.sn48.zivili.ch/meow/drone-deploy:amd64-1.0.0
pull: never
settings:
ssh_port:
from_secret: SSH_PORT
# this is required for the moment to generate the .docker/config.json
# drone is failing to do it on its own at the moment
dockerconfigjson:
from_secret: dockerconfigjson
# use portus or directly docker logins
portus_user:
from_secret: PORTUS_USER
portus_password:
from_secret: PORTUS_PASSWORD
# used by deploy to login to deploy server
ssh_host:
from_secret: SSH_HOST
ssh_user:
from_secret: SSH_USER
ssh_key:
from_secret: SSH_KEY
ssh_fingerprint:
from_secret: SSH_FINGERPRINT
# used by the deploy script to gather all project's .env values from vault
drone_agent1_token:
from_secret: DRONE_AGENT1_TOKEN
# used by deploy script to know where to gather secrets from
vault_api_url:
from_secret: VAULT_API_URL
---
kind: secret
name: SSH_HOST
get:
path: kv/data/__drone-admin-secrets
name: SSH_HOST
---
kind: secret
name: SSH_USER
get:
path: kv/data/__drone-admin-secrets
name: SSH_USER
---
kind: secret
name: SSH_KEY
get:
path: kv/data/__drone-admin-secrets
name: SSH_KEY
---
kind: secret
name: DRONE_AGENT1_TOKEN
get:
path: kv/data/__drone-admin-secrets
name: DRONE_AGENT1_TOKEN
---
kind: secret
name: VAULT_API_URL
get:
path: kv/data/__drone-admin-secrets
name: VAULT_API_URL
---
kind: secret
name: PORTUS_USER
get:
path: kv/data/__drone-admin-secrets
name: PORTUS_USER
---
kind: secret
name: PORTUS_PASSWORD
get:
path: kv/data/__drone-admin-secrets
name: PORTUS_PASSWORD
---
kind: secret
name: dockerconfigjson
get:
path: kv/data/__drone-admin-secrets
name: dockerconfigjson
image_pull_secrets:
from_secret: dockerconfigjson
---
kind: secret
name: SSH_PORT
get:
path: kv/data/__drone-admin-secrets
name: SSH_PORT
---
kind: secret
name: SSH_FINGERPRINT
get:
path: kv/data/__drone-admin-secrets
name: SSH_FINGERPRINT

3
.gitignore vendored

@ -0,0 +1,3 @@
.env*
themeforest-*
display/

@ -0,0 +1,140 @@
version: "3.9"
services:
wp_db:
image: mariadb:11
container_name: "${REVERSE_DOMAIN}_wp_db"
environment:
MYSQL_ROOT_PASSWORD: "${DB_ROOT_PASSWORD}"
MYSQL_DATABASE: "${DB_NAME}"
MYSQL_USER: "${DB_USER}"
MYSQL_PASSWORD: "${DB_PASSWORD}"
expose:
- 3306
volumes:
- wp_mysql:/var/lib/mysql
restart: always
networks:
- app_network
wp_db_phpmyadmin:
image: phpmyadmin/phpmyadmin
container_name: "${REVERSE_DOMAIN}_db_phpmyadmin"
depends_on:
- wp_db
environment:
PMA_HOST: "${REVERSE_DOMAIN}_wp_db"
PMA_PORT: 3306
MYSQL_ROOT_PASSWORD: "${DB_ROOT_PASSWORD}"
MYSQL_DATABASE: "${DB_NAME}"
MYSQL_USER: "${DB_USER}"
MYSQL_PASSWORD: "${DB_PASSWORD}"
UPLOAD_LIMIT: 300M
expose:
- 80
labels:
- "traefik.enable=true"
- "traefik.http.routers.${REVERSE_DOMAIN}_pma.rule=Host(`pma.${APPLICATION_DOMAIN_NAME}`)"
- "traefik.http.routers.${REVERSE_DOMAIN}_pma.entrypoints=websecure"
- "traefik.http.routers.${REVERSE_DOMAIN}_pma.tls.certresolver=myresolver"
- "traefik.http.services.${REVERSE_DOMAIN}_pma.loadbalancer.server.port=80"
# VERY IMPORTANT WHEN TWO NETWORKS
- "traefik.docker.network=shared_network"
restart: always
networks:
- shared_network
- app_network
wp_filebrowser:
image: filebrowser/filebrowser:latest
container_name: "${REVERSE_DOMAIN}_filebrowser"
volumes:
- wp_data:/srv
- filebrowser_db:/database
- ./docker/filebrowser/settings.json:/config/settings.json
environment:
- PUID=$(id -u)
- PGID=$(id -g)
expose:
- 80
labels:
- "traefik.enable=true"
- "traefik.http.routers.${REVERSE_DOMAIN}_filebrowser.rule=Host(`ftp.${APPLICATION_DOMAIN_NAME}`)"
- "traefik.http.routers.${REVERSE_DOMAIN}_filebrowser.entrypoints=websecure"
- "traefik.http.routers.${REVERSE_DOMAIN}_filebrowser.tls.certresolver=myresolver"
- "traefik.http.services.${REVERSE_DOMAIN}_filebrowser.loadbalancer.server.port=80"
- "traefik.docker.network=shared_network"
restart: always
networks:
- shared_network
- app_network
wp:
image: "${DOCKER_IMAGE}:${DOCKER_IMAGE_TAG}"
container_name: "${REVERSE_DOMAIN}_wp"
depends_on:
- wp_db
environment:
WORDPRESS_DB_HOST: "${REVERSE_DOMAIN}_wp_db"
WORDPRESS_DB_NAME: "${DB_NAME}"
WORDPRESS_DB_USER: "${DB_USER}"
WORDPRESS_DB_PASSWORD: "${DB_PASSWORD}"
WORDPRESS_DB_CHARSET: "utf8"
WORDPRESS_DB_COLLATE: ""
WORDPRESS_AUTH_KEY: "${AUTH_KEY}"
WORDPRESS_SECURE_AUTH_KEY: "${SECURE_AUTH_KEY}"
WORDPRESS_LOGGED_IN_KEY: "${LOGGED_IN_KEY}"
WORDPRESS_NONCE_KEY: "${NONCE_KEY}"
WORDPRESS_AUTH_SALT: "${AUTH_SALT}"
WORDPRESS_SECURE_AUTH_SALT: "${SECURE_AUTH_SALT}"
WORDPRESS_LOGGED_IN_SALT: "${LOGGED_IN_SALT}"
WORDPRESS_NONCE_SALT: "${NONCE_SALT}"
WORDPRESS_TABLE_PREFIX: "${TABLE_PREFIX}"
WORDPRESS_CONFIG_EXTRA: |
$$to_bool = include __DIR__ . '/to-bool.php';
define( 'WP_DEBUG', $$to_bool('${WP_DEBUG}') );
define( 'WP_DEBUG_LOG', $$to_bool('${WP_DEBUG_LOG}') );
define( 'WP_DEBUG_DISPLAY', $$to_bool('${WP_DEBUG_DISPLAY}') );
define( 'DISABLE_WP_CRON', $$to_bool('${DISABLE_WP_CRON}') );
expose:
- 80
labels:
- "traefik.enable=true"
- "traefik.http.routers.${REVERSE_DOMAIN}.rule=Host(`${APPLICATION_DOMAIN_NAME}`)"
- "traefik.http.routers.${REVERSE_DOMAIN}.entrypoints=websecure"
- "traefik.http.routers.${REVERSE_DOMAIN}.tls.certresolver=myresolver"
- "traefik.http.services.${REVERSE_DOMAIN}.loadbalancer.server.port=80"
- "traefik.docker.network=shared_network"
volumes:
# only user data persists
- wp_content:/var/www/html/wp-content
restart: always
networks:
- shared_network
- app_network
wp_cron:
image: registry.sn48.zivili.ch/meow/wp-cron:amd64-1.0.0
container_name: "${REVERSE_DOMAIN}_wp_cron"
depends_on:
- wp
networks:
- app_network
networks:
shared_network:
name: shared_network
external: true
app_network:
name: ${REVERSE_DOMAIN}-app_network
volumes:
wp_mysql:
name: "${REVERSE_DOMAIN}_wp_db-volume"
external: true
wp_content:
name: "${REVERSE_DOMAIN}_wp-data"
external: true
filebrowser_db:
name: "${REVERSE_DOMAIN}_filebrowser_db"
external: true

@ -0,0 +1,23 @@
FROM wordpress:latest
# WP-CLI and other extras …
RUN curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar \
&& chmod +x wp-cli.phar && mv wp-cli.phar /usr/local/bin/wp
# keep the upstream entrypoint
RUN mv /usr/local/bin/docker-entrypoint.sh /usr/local/bin/docker-entrypoint-upstream.sh
# tracked application code
COPY docker/wordpress/public_dir/themes /usr/src/themes
COPY docker/wordpress/public_dir/to-bool.php /usr/src/to-bool.php
COPY docker/wordpress/duplicator-initial-deploy /usr/src/duplicator
COPY docker/wordpress/php.ini /usr/local/etc/php/php.ini
# custom wrapper
COPY docker/wordpress/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
EXPOSE 80
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["apache2-foreground"]

@ -0,0 +1,29 @@
#!/bin/bash
set -euo pipefail
################################################################################
# ONE-TIME Duplicator restore
################################################################################
if [ ! -f /var/www/html/wp-content/.duplicator_restored ]; then
echo "▶ First run copy Duplicator package"
mkdir -p /var/www/html
cp -r /usr/src/duplicator/* /var/www/html/
chown -R www-data:www-data /var/www/html
touch /var/www/html/wp-content/.duplicator_restored
echo "✓ Package placed browse /installer.php to finish the restore"
fi
################################################################################
# ALWAYS sync the code we keep under version control
################################################################################
echo "▶ Syncing version-controlled themes"
rsync -a --delete /usr/src/themes/ /var/www/html/wp-content/themes/
################################################################################
# (optional) run safe automatic DB migrations, plugin installs, etc.
# wp core update-db --yes
# wp plugin update --all --quiet
################################################################################
# Hand back to the real WP entrypoint
exec /usr/local/bin/docker-entrypoint-upstream.sh "$@"

File diff suppressed because it is too large Load Diff

@ -0,0 +1,5 @@
; php.ini
memory_limit = 512M
upload_max_filesize = 100M
post_max_size = 100M
max_execution_time = 300

Binary file not shown.

@ -0,0 +1,13 @@
<?php
$env_to_bool = function ($v): bool {
if (is_bool($v)) return $v;
if (is_numeric($v)) return (bool) intval($v);
if (is_string($v)) {
$n = mb_strtolower(trim($v));
if (in_array($n, ['1','true','on','yes','y','t'], true)) return true;
if (in_array($n, ['0','false','off','no','n','f'], true)) return false;
}
throw new Exception('Could not convert value to bool');
};
return $env_to_bool;

@ -0,0 +1,8 @@
FROM alpine
# Install curl and set up the cron job
RUN apk add --no-cache curl && \
echo "*/5 * * * * curl http://wp:80/wp-cron.php?doing_wp_cron" > /etc/crontabs/root
# Run crond in the foreground
CMD ["crond", "-f"]
Loading…
Cancel
Save