From debdbee3cb8710ea2c12b37ab4a64292237d2da0 Mon Sep 17 00:00:00 2001 From: CWei Date: Mon, 12 Jan 2026 13:30:01 +0800 Subject: [PATCH] refactor(docker): provide default env values for zero-config startup - Move common environment defaults into docker-compose - Remove requirement to manually copy .env.example - Simplify Nginx and service configuration for quick deployment --- .env.example | 2 +- README.md | 11 +- ...er-compose-dev.yaml => docker-compose.yaml | 132 +++++++++--------- nginx/.gitignore | 3 - nginx/nginx.conf | 2 +- nginx/whitelist.conf | 20 +++ nginx/whitelist.conf.example | 7 - 7 files changed, 90 insertions(+), 87 deletions(-) rename docker-compose-dev.yaml => docker-compose.yaml (63%) create mode 100755 nginx/whitelist.conf delete mode 100755 nginx/whitelist.conf.example diff --git a/.env.example b/.env.example index ef05e98..e47b296 100755 --- a/.env.example +++ b/.env.example @@ -1,6 +1,6 @@ # Docker compose setting COMPOSE_PATH_SEPARATOR=: -COMPOSE_DEV=docker-compose-dev.yaml +COMPOSE_DEV=docker-compose.yaml COMPOSE_PROD=docker-compose-prod.yaml COMPOSE_FILE=${COMPOSE_DEV} diff --git a/README.md b/README.md index 30d84d3..fc76473 100755 --- a/README.md +++ b/README.md @@ -35,21 +35,14 @@ This project is a ready-to-use fullstack template that leverages Docker Compose #### 3. **Configure environment variables** - Copy `.env.example` to `.env` and edit as needed. - - ```bash - cp .env.example .env - ``` + If you want to customize settings, copy `.env.example` to `.env` and edit as needed. > Set the `COMPOSE_FILE` environment variable to switch between development and production modes. #### 4. **Set up Nginx IP whitelist and SSL certificates** - - Copy `whitelist.conf.example` to `whitelist.conf` and edit as needed. + If you need to restrict the range of allowed IP addresses, edit this file. - ```bash - cp nginx/whitelist.conf.example nginx/whitelist.conf - ``` - To enable SSL (HTTPS), you need to configure SSL settings in your `.env` file and place your SSL certificates in the `nginx/ssl` directory. - Env setting: diff --git a/docker-compose-dev.yaml b/docker-compose.yaml similarity index 63% rename from docker-compose-dev.yaml rename to docker-compose.yaml index d1d802e..52d0dd1 100755 --- a/docker-compose-dev.yaml +++ b/docker-compose.yaml @@ -13,28 +13,28 @@ services: - ./nginx/docker-entrypoint.sh:/docker-entrypoint.sh environment: - NODE_ENV=development - - TZ=${TIMEZONE} - - HOSTNAME=${HOSTNAME} + - TZ=${TIMEZONE:-UTC} + - HOSTNAME=${HOSTNAME:-localhost} # SSL settings - - SSL_ENABLE=${SSL_ENABLE} - - SSL_CERT_FILE=${SSL_CERT_FILE} - - SSL_KEY_FILE=${SSL_KEY_FILE} + - SSL_ENABLE=${SSL_ENABLE:-false} + - SSL_CERT_FILE=${SSL_CERT_FILE:-cert.pem} + - SSL_KEY_FILE=${SSL_KEY_FILE:-privkey.pem} # Port settings - - FRONTEND_PORT=${FRONTEND_PORT} - - BACKEND_PORT=${BACKEND_PORT} - - PMA_PORT=${PMA_PORT} - - GRAFANA_PORT=${GRAFANA_PORT} - - REDIS_INSIGHT_PORT=${REDIS_INSIGHT_PORT} + - FRONTEND_PORT=${FRONTEND_PORT:-3000} + - BACKEND_PORT=${BACKEND_PORT:-5000} + - PMA_PORT=${PMA_PORT:-8080} + - GRAFANA_PORT=${GRAFANA_PORT:-3001} + - REDIS_INSIGHT_PORT=${REDIS_INSIGHT_PORT:-5540} # Redis Insight authentication - - REDIS_INSIGHT_USER=${REDIS_INSIGHT_USER} - - REDIS_INSIGHT_PASSWORD=${REDIS_INSIGHT_PASSWORD} + - REDIS_INSIGHT_USER=${REDIS_INSIGHT_USER:-} + - REDIS_INSIGHT_PASSWORD=${REDIS_INSIGHT_PASSWORD:-} entrypoint: ["/docker-entrypoint.sh"] ports: - - "${FRONTEND_PORT}:${FRONTEND_PORT}" - - "${BACKEND_PORT}:${BACKEND_PORT}" - - "${PMA_PORT}:${PMA_PORT}" - - "${GRAFANA_PORT}:${GRAFANA_PORT}" - - "${REDIS_INSIGHT_PORT}:${REDIS_INSIGHT_PORT}" + - "${FRONTEND_PORT:-3000}:${FRONTEND_PORT:-3000}" + - "${BACKEND_PORT:-5000}:${BACKEND_PORT:-5000}" + - "${PMA_PORT:-8080}:${PMA_PORT:-8080}" + - "${GRAFANA_PORT:-3001}:${GRAFANA_PORT:-3001}" + - "${REDIS_INSIGHT_PORT:-5540}:${REDIS_INSIGHT_PORT:-5540}" depends_on: frontend: condition: service_healthy @@ -57,15 +57,15 @@ services: - ./frontend:/app environment: - NODE_ENV=development - - TZ=${TIMEZONE} - - SITE_URL=${SITE_URL} - - VITE_SSL_ENABLE=${SSL_ENABLE} - - VITE_PROJECT_NAME=${PROJECT_NAME} - - VITE_PROJECT_VERSION=${PROJECT_VERSION} - - VITE_PROJECT_DESCRIPTION=${PROJECT_DESCRIPTION} + - TZ=${TIMEZONE:-UTC} + - SITE_URL=${SITE_URL:-http://localhost} + - VITE_SSL_ENABLE=${SSL_ENABLE:-false} + - VITE_PROJECT_NAME=${PROJECT_NAME:-docker-fullstack-template} + - VITE_PROJECT_VERSION=${PROJECT_VERSION:-1.0.0} + - VITE_PROJECT_DESCRIPTION=${PROJECT_DESCRIPTION:-Docker fullstack template} # API settings - - VITE_API_HOST=${API_HOST} - - VITE_API_PORT=${API_PORT} + - VITE_API_HOST=${API_HOST:-localhost} + - VITE_API_PORT=${API_PORT:-5000} command: ["sh", "./init-dev.sh"] depends_on: backend: @@ -85,30 +85,30 @@ services: volumes: - ./backend:/app environment: - - TZ=${TIMEZONE} + - TZ=${TIMEZONE:-UTC} - DEBUG_MODE=true - - LOG_LEVEL=${LOG_LEVEL} - - SSL_ENABLE=${SSL_ENABLE} - - SECRET_KEY=${SECRET_KEY} - - PROJECT_NAME=${PROJECT_NAME} - - PROJECT_VERSION=${PROJECT_VERSION} - - PROJECT_DESCRIPTION=${PROJECT_DESCRIPTION} + - LOG_LEVEL=${LOG_LEVEL:-INFO} + - SSL_ENABLE=${SSL_ENABLE:-false} + - SECRET_KEY=${SECRET_KEY:-change-me} + - PROJECT_NAME=${PROJECT_NAME:-docker-fullstack-template} + - PROJECT_VERSION=${PROJECT_VERSION:-0.1.0} + - PROJECT_DESCRIPTION=${PROJECT_DESCRIPTION:-Docker fullstack template} # CORS settings - - HOSTNAME=${HOSTNAME} - - BACKEND_PORT=${BACKEND_PORT} - - FRONTEND_PORT=${FRONTEND_PORT} + - HOSTNAME=${HOSTNAME:-localhost} + - BACKEND_PORT=${BACKEND_PORT:-5000} + - FRONTEND_PORT=${FRONTEND_PORT:-3000} # Database settings - - DATABASE_URL=mysql+pymysql://${DB_USER}:${DB_PASSWORD}@mariadb/${DB_DATABASE} - - DATABASE_URL_TEST=mysql+pymysql://${DB_USER}:${DB_PASSWORD}@mariadb/test_${DB_DATABASE} - - DB_POOL_SIZE=${DB_POOL_SIZE} - - DB_POOL_TIMEOUT=${DB_POOL_TIMEOUT} - - DB_POOL_RECYCLE=${DB_POOL_RECYCLE} - - DB_MAX_OVERFLOW=${DB_MAX_OVERFLOW} - - DB_CONNECT_TIMEOUT=${DB_CONNECT_TIMEOUT} - - DB_READ_TIMEOUT=${DB_READ_TIMEOUT} - - DB_WRITE_TIMEOUT=${DB_WRITE_TIMEOUT} + - DATABASE_URL=mysql+pymysql://${DB_USER:-app}:${DB_PASSWORD:-app}@mariadb/${DB_DATABASE:-app} + - DATABASE_URL_TEST=mysql+pymysql://${DB_USER:-app}:${DB_PASSWORD:-app}@mariadb/test_${DB_DATABASE:-app} + - DB_POOL_SIZE=${DB_POOL_SIZE:-10} + - DB_POOL_TIMEOUT=${DB_POOL_TIMEOUT:-30} + - DB_POOL_RECYCLE=${DB_POOL_RECYCLE:-3600} + - DB_MAX_OVERFLOW=${DB_MAX_OVERFLOW:-20} + - DB_CONNECT_TIMEOUT=${DB_CONNECT_TIMEOUT:-10} + - DB_READ_TIMEOUT=${DB_READ_TIMEOUT:-30} + - DB_WRITE_TIMEOUT=${DB_WRITE_TIMEOUT:-30} # Redis settings - - REDIS_URL=redis://:${REDIS_PASSWORD}@redis:6379/0 + - REDIS_URL=redis://:${REDIS_PASSWORD:-redis}@redis:6379/0 command: ["sh", "./init-dev.sh"] depends_on: mariadb: @@ -127,11 +127,11 @@ services: mariadb: image: mariadb:11.3 environment: - - TZ=${TIMEZONE} - - MYSQL_DATABASE=${DB_DATABASE} - - MYSQL_USER=${DB_USER} - - MYSQL_PASSWORD=${DB_PASSWORD} - - MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWORD} + - TZ=${TIMEZONE:-UTC} + - MYSQL_DATABASE=${DB_DATABASE:-app} + - MYSQL_USER=${DB_USER:-app} + - MYSQL_PASSWORD=${DB_PASSWORD:-app} + - MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWORD:-root} volumes: - db-data:/var/lib/mysql - ./db/custom.cnf:/etc/mysql/conf.d/custom.cnf @@ -149,10 +149,10 @@ services: phpmyadmin: image: phpmyadmin/phpmyadmin:5.2.2 environment: - - TZ=${TIMEZONE} + - TZ=${TIMEZONE:-UTC} - PMA_HOST=mariadb - PMA_USER=root - - PMA_PASSWORD=${DB_ROOT_PASSWORD} + - PMA_PASSWORD=${DB_ROOT_PASSWORD:-root} volumes: - ./phpmyadmin/config.user.inc.php:/etc/phpmyadmin/config.user.inc.php depends_on: @@ -165,8 +165,8 @@ services: redis: image: redis:8.4.0 environment: - - TZ=${TIMEZONE} - - REDIS_PASSWORD=${REDIS_PASSWORD} + - TZ=${TIMEZONE:-UTC} + - REDIS_PASSWORD=${REDIS_PASSWORD:-redis} volumes: - redis-data:/data - ./redis/redis.conf:/usr/local/etc/redis/redis.conf @@ -180,7 +180,7 @@ services: - backend-network restart: always healthcheck: - test: ["CMD-SHELL", "redis-cli -a ${REDIS_PASSWORD} ping | grep -q PONG"] + test: ["CMD-SHELL", "redis-cli -a ${REDIS_PASSWORD:-redis} ping | grep -q PONG"] start_period: 30s interval: 10s timeout: 5s @@ -189,12 +189,12 @@ services: redis-insight: image: redis/redisinsight:2.70 environment: - - TZ=${TIMEZONE} + - TZ=${TIMEZONE:-UTC} - RI_REDIS_HOST=redis - RI_REDIS_PORT=6379 - - RI_REDIS_ALIAS=${PROJECT_NAME} + - RI_REDIS_ALIAS=${PROJECT_NAME:-docker-fullstack-template} - RI_REDIS_USERNAME=default - - RI_REDIS_PASSWORD=${REDIS_PASSWORD} + - RI_REDIS_PASSWORD=${REDIS_PASSWORD:-redis} volumes: - redis-insight-data:/data depends_on: @@ -213,7 +213,7 @@ services: loki: image: grafana/loki:3.5.3 environment: - - TZ=${TIMEZONE} + - TZ=${TIMEZONE:-UTC} volumes: - loki-data:/loki - loki-wal-data:/wal @@ -236,7 +236,7 @@ services: alloy: image: grafana/alloy:v1.10.0 environment: - - TZ=${TIMEZONE} + - TZ=${TIMEZONE:-UTC} volumes: - alloy-data:/data - ./backend/logs:/var/log/backend @@ -252,12 +252,12 @@ services: grafana: image: grafana/grafana:12.2.0-16557133545 environment: - - TZ=${TIMEZONE} - - SSL_ENABLE=${SSL_ENABLE} - - GRAFANA_HOST=${GRAFANA_HOST} - - GRAFANA_PORT=${GRAFANA_PORT} - - GF_SECURITY_ADMIN_USER=${GRAFANA_USER} - - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD} + - TZ=${TIMEZONE:-UTC} + - SSL_ENABLE=${SSL_ENABLE:-false} + - GRAFANA_HOST=${GRAFANA_HOST:-localhost} + - GRAFANA_PORT=${GRAFANA_PORT:-3001} + - GF_SECURITY_ADMIN_USER=${GRAFANA_USER:-admin} + - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD:-admin} - GF_PANELS_DISABLE_SANITIZE_HTML=true - GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS=* - GF_USERS_ALLOW_SIGN_UP=false diff --git a/nginx/.gitignore b/nginx/.gitignore index eedf8f7..a0b185c 100644 --- a/nginx/.gitignore +++ b/nginx/.gitignore @@ -1,6 +1,3 @@ -# Whitelist -whitelist.conf - # SSL *.pem *.key diff --git a/nginx/nginx.conf b/nginx/nginx.conf index 5331f92..d8e70c4 100755 --- a/nginx/nginx.conf +++ b/nginx/nginx.conf @@ -42,7 +42,7 @@ http { # IP whitelist configuration geo $allowed { - default 0; # 0 - blocked, 1 - allowed + default 1; # 0 - blocked, 1 - allowed include /etc/nginx/whitelist.conf; } diff --git a/nginx/whitelist.conf b/nginx/whitelist.conf new file mode 100755 index 0000000..c8de7da --- /dev/null +++ b/nginx/whitelist.conf @@ -0,0 +1,20 @@ +# IP whitelist for `geo $allowed` +# +# Default behavior: +# - `nginx.conf` uses `default 1;` => allow all requests +# +# Enable whitelist mode: +# - Change `nginx.conf` to `default 0;` +# - Then uncomment/add allowed IPs/subnets below (use `1;` to allow) +# +# Examples: +# - Allow localhost +# 127.0.0.1/32 1; +# +# - Allow private networks +# 10.0.0.0/8 1; +# 172.16.0.0/12 1; +# 192.168.0.0/16 1; +# +# - Optional +# 100.64.0.0/10 1; \ No newline at end of file diff --git a/nginx/whitelist.conf.example b/nginx/whitelist.conf.example deleted file mode 100755 index 1eb19f2..0000000 --- a/nginx/whitelist.conf.example +++ /dev/null @@ -1,7 +0,0 @@ -# To allow all IPs, set 'default 1;' in `nginx.conf` (do not add 0.0.0.0/0 here) - -# Allow specific subnet -192.168.1.0/24 1; - -# Allow specific IP -192.168.0.1 1; \ No newline at end of file