Skip to content

Commit

Permalink
refactor : all modules
Browse files Browse the repository at this point in the history
  • Loading branch information
patternhelloworld committed Oct 29, 2024
1 parent d16492f commit 3adc557
Show file tree
Hide file tree
Showing 35 changed files with 330 additions and 250 deletions.
3 changes: 1 addition & 2 deletions .env.example.local
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# IMPORTANT - mac : docker.for.mac.localhost / win : host.docker.internal OR you can just type your host IP.
HOST_IP=host.docker.internal
APP_ENV=local

Expand All @@ -9,10 +8,10 @@ COMMERCIAL_SSL_NAME=yyy

DOCKER_LAYER_CORRUPTION_RECOVERY=false


NGINX_RESTART=false
CONSUL_RESTART=false


# The method of acquiring Docker images:
# build (Used in developer's local environment or during Jenkins builds when a new image needs to be built, so this module is typically used)
# registry (Used on deployment servers where images are fetched from a repository, so this module is used)
Expand Down
4 changes: 3 additions & 1 deletion .env.example.real
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# IMPORTANT - mac : docker.for.mac.localhost / win : host.docker.internal OR you can just type your host IP.
HOST_IP=host.docker.internal
APP_ENV=real

Expand All @@ -15,6 +14,7 @@ DOCKER_LAYER_CORRUPTION_RECOVERY=false
NGINX_RESTART=false
CONSUL_RESTART=false


# The method of acquiring Docker images:
# build (Used in developer's local environment or during Jenkins builds when a new image needs to be built, so this module is typically used)
# registry (Used on deployment servers where images are fetched from a repository, so this module is used)
Expand Down Expand Up @@ -58,6 +58,8 @@ DOCKER_BUILD_ARGS={}
DOCKER_COMPOSE_REAL_SELECTIVE_VOLUMES=[]
# This is added on docker-compose-${project_name}-nginx.yml
DOCKER_COMPOSE_NGINX_SELECTIVE_VOLUMES=["./shared/nginx-error-logs:/var/log/nginx"]


NGINX_CLIENT_MAX_BODY_SIZE=50M

# Format : docker-compose-${project_name}-${app_env}-original-ready.yml
Expand Down
1 change: 1 addition & 0 deletions .env.java.real
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ COMMERCIAL_SSL_NAME=yyy

DOCKER_LAYER_CORRUPTION_RECOVERY=false


NGINX_RESTART=false
CONSUL_RESTART=false

Expand Down
3 changes: 3 additions & 0 deletions .env.java.real.commercial.ssl.sample
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ COMMERCIAL_SSL_NAME=yourdomain.com

DOCKER_LAYER_CORRUPTION_RECOVERY=false


NGINX_RESTART=false
CONSUL_RESTART=false


# The method of acquiring Docker images:
# build (Used in developer's local environment or during Jenkins builds when a new image needs to be built, so this module is typically used)
# registry (Used on deployment servers where images are fetched from a repository, so this module is used for the production server)
Expand Down Expand Up @@ -50,6 +52,7 @@ DOCKER_BUILD_ARGS={"DOCKER_BUILDKIT":"1","PROJECT_ROOT_IN_CONTAINER":"/var/www/s
DOCKER_COMPOSE_REAL_SELECTIVE_VOLUMES=["/var/web/files/spring-sample-h-auth:/var/www/files","/var/web/project/spring-sample-h-auth/src/main/resources:/var/www/server/spring-sample-h-auth/src/main/resources"]
DOCKER_COMPOSE_NGINX_SELECTIVE_VOLUMES=["/var/web/files/nginx/spring-sample-h-auth/logs:/var/log/nginx"]


NGINX_CLIENT_MAX_BODY_SIZE=50M

USE_MY_OWN_APP_YML=false
Expand Down
6 changes: 4 additions & 2 deletions .env.php.local
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
HOST_IP=host.docker.internal
APP_ENV=local

APP_URL=http://localhost:8080
APP_URL=http://localhost:8081

USE_COMMERCIAL_SSL=yyy
COMMERCIAL_SSL_NAME=yyy

DOCKER_LAYER_CORRUPTION_RECOVERY=false


NGINX_RESTART=false
CONSUL_RESTART=false

Expand All @@ -25,7 +26,7 @@ GIT_IMAGE_VERSION=1.0.0

PROJECT_NAME=laravel_crud_boilerplate
PROJECT_LOCATION=/var/www/app
PROJECT_PORT=8080
PROJECT_PORT=8081
# Example (8093,8094,11000...)
ADDITIONAL_PORTS=

Expand All @@ -49,6 +50,7 @@ DOCKER_COMPOSE_ENVIRONMENT={"XDEBUG_CONFIG":"idekey=IDE_DEBUG","PHP_IDE_CONFIG":
DOCKER_BUILD_ARGS={"SAMPLE":"YAHOO","SAMPLE2":"YAHOO2"}
DOCKER_COMPOSE_NGINX_SELECTIVE_VOLUMES=[]


NGINX_CLIENT_MAX_BODY_SIZE=50M

USE_MY_OWN_APP_YML=false
Expand Down
4 changes: 2 additions & 2 deletions .env.php.real
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ HOST_IP=host.docker.internal
APP_ENV=real

# I recommend you should type your exposed formal URL or IP such as https://test.com for the test of 'check_availability_out_of_container' in the script 'run.sh'
APP_URL=https://localhost:8080
APP_URL=https://localhost:8081

USE_COMMERCIAL_SSL=false
COMMERCIAL_SSL_NAME=yyy
Expand All @@ -26,7 +26,7 @@ GIT_IMAGE_VERSION=1.0.0

PROJECT_NAME=laravel_crud_boilerplate
PROJECT_LOCATION=/var/www/app
PROJECT_PORT=8080
PROJECT_PORT=8081
# Example (8093,8094,11000...)
ADDITIONAL_PORTS=

Expand Down
44 changes: 35 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Docker-Blue-Green-Runner

> One Simple Zero-Downtime Blue-Green Deployment Starting from your Dockerfiles
> One Simple Zero-Downtime Blue-Green Deployment with your Dockerfiles
Deploying web projects should be [simple, with high availability and security](https://github.com/Andrew-Kang-G/docker-blue-green-runner?tab=readme-ov-file#Quick-Guide-on-Usage).

Expand All @@ -9,6 +9,7 @@ Deploying web projects should be [simple, with high availability and security](h

## Table of Contents
- [Features](#features)
- [Why would I use this over Traefik?](#why-would-i-use-this-over-traefik)
- [Requirements](#requirements)
- [Quick Start with Samples](#quick-start-with-samples)
- [Provided Samples](#provided-samples)
Expand Down Expand Up @@ -40,18 +41,18 @@ Deploying web projects should be [simple, with high availability and security](h
- [Extra Information](#extra-information)
- [Test](#test)
- [Check Source Integrity of 'Docker-Blue-Green-Runner'](#check-source-integrity-of-docker-blue-green-runner)
- [Structure](#structure)
- [Concurrent Running for this App](#concurrent-running-for-this-app)
- [Docker Swarm](#docker-swarm)


---

## Features

- ``Pure Docker`` (No Need for Binary Installation Files and Complex Configurations)
- On Linux, you only need to have ``docker, docker-compose`` and some helping libraries such as ``git, curl, bash, yq(v4.35.1)`` installed.
- So, this is available for both non-cloud and cloud environments. You only need one machine.
- With your ``.env, project, and its sole Dockerfile``, Docker-Blue-Green-Runner manages the remainder of the Continuous Deployment (CD) process with [wait-for-it](https://github.com/vishnubob/wait-for-it), [consul-template](https://github.com/hashicorp/consul-template) and [Nginx](https://github.com/nginx/nginx).
- With your ``.env, project, and its sole Dockerfile``, Docker-Blue-Green-Runner manages the remainder of the Continuous Deployment (CD) process with [wait-for-it](https://github.com/vishnubob/wait-for-it), [consul-template](https://github.com/hashicorp/consul-template) and [Nginx](https://github.com/nginx/nginx). Just run ``bash run.sh``.


![consists-of.png](/documents/images/consists-of.png )
Expand All @@ -61,6 +62,23 @@ Deploying web projects should be [simple, with high availability and security](h
- While Kubernetes excels in multi-machine environments with the support of Layer 7 (L7) technologies (I would definitely use Kubernetes in that case), this approach is ideal for scenarios where only one or two machines are available.
- However, ``for deployments involving more machines, traditional Layer 4 (L4) load-balancer using servers could be utilized.``

## Why would I use this over Traefik?

- **Unpredictable Errors in Reverse Proxy**
- Traefik offers powerful dynamic configuration and service discovery; however, certain errors, such as a failure to detect containers (due to issues like unrecognized certificates), can lead to frustrating 404 errors that are hard to trace through logs alone.
- https://stackoverflow.com/questions/76660749/traefik-404-page-not-found-when-use-https
- https://community.traefik.io/t/getting-bad-gateway-404-page-when-supposed-to-route-to-container-port-8443/20398
- Docker-Blue-Green-Runner manipulates NGINX configuration files directly to ensure container accessibility. It also tests configuration files by launching a test NGINX Docker instance, and if an NGINX config update via Consul-Template fails, Contingency Plan provided is activated to ensure connectivity to your containers.
- Additionally, the code is written in shell script, making it easier to trace the exact code section where an error occurs (as opposed to working with a binary).

- **From Scratch**
- Docker-Blue-Green-Runner's `run.sh` script is designed to simplify deployment: "With your `.env`, project, and a single Dockerfile, simply run 'bash run.sh'." This script covers the entire process from Dockerfile build to server deployment from scratch.
- In contrast, Traefik requires the creation and gradual adjustment of various configuration files, which can introduce the types of errors mentioned above.

- **Speed**
- NGINX generally offers faster performance, though I acknowledge that Traefik's robust features can offset this advantage.


## Requirements


Expand Down Expand Up @@ -150,14 +168,16 @@ sudo bash run.sh


### How to Start with a PHP Sample (Real, HTTPS self-signed SSL)
- Check the port number 8080 available before getting this started.
- Check the port number 8081 available before getting this started.

Differences between ``./samples/laravel-crud-boilerplate/Dockerfile.local`` and ``./samples/laravel-crud-boilerplate/Dockerfile.real``

1) Staging build : (Local - no, Real - yes to reduce the size of the image)
2) Volume for the whole project : (Local - yes, Real - no. copy the whole project only one time)
3) SSL : (Local - not required, Real - yes, you can. as long as you set APP_URL on .env starting with 'https')

- The runner detects file names of ``Dockefile`` or ``Dockerfile.${app_env}``

A PHP sample project (https://github.com/Andrew-Kang-G/laravel-crud-boilerplate) that comes with an MIT License and serves as an example for demonstrating how to use Docker-Blue-Green-Runner.

```shell
Expand All @@ -172,16 +192,16 @@ docker-compose up -d
# Go back to the root
cd ../../
cp -f .env.php.real .env
# For WIN WSL2, \r on shell scripts can cause issues.
# For WIN 10 WSL2, \r on shell scripts can cause issues.
sed -i -e 's/\r$//' samples/laravel-crud-boilerplate/.docker/sh/update/real/run.sh
# In case you use a Mac, you are not available with 'host.docker.internal', so change 'host.docker.internal' to your host IP in the ./.env file.
# [NOTE] Initially, since the sample project does not have the "vendor" installed, the Health Check stage may take longer.
sudo bash run.sh
```
Open https://localhost:8080 (NO http. see .env. if you'd like http, change APP_URL) in your browser, and test with the Postman samples (./samples/laravel-crud-boilerplate/reference/postman) and debug with the following instruction ( https://github.com/Andrew-Kang-G/laravel-crud-boilerplate#debugging ).
Open https://localhost:8081 (NO http. see .env. if you'd like http, change APP_URL) in your browser, and test with the Postman samples (./samples/laravel-crud-boilerplate/reference/postman) and debug with the following instruction ( https://github.com/Andrew-Kang-G/laravel-crud-boilerplate#debugging ).
### How to Start with a PHP Sample (Local).
- Check the port number 8080 available before getting this started.
- Check the port number 8081 available before getting this started.
A PHP sample project (https://github.com/Andrew-Kang-G/laravel-crud-boilerplate) that comes with an MIT License and serves as an example for demonstrating how to use Docker-Blue-Green-Runner.
Expand Down Expand Up @@ -538,7 +558,7 @@ graph TD;
GIT_TOKEN_IMAGE_LOAD_FROM_PASSWORD=12345
GIT_IMAGE_VERSION=1.0.0
```
- ``GIT_IMAGE_LOAD_FROM`` is 'build', ``docker-blue-green-runner`` builds your ``Dockerfile``, while it is 'registry', the runner downloads ``app, nginx, consul, registrator`` from such as the example code on ``util.sh``.
- ``GIT_IMAGE_LOAD_FROM`` is 'build', ``docker-blue-green-runner`` builds your ``Dockerfile``, while it is 'registry', the runner downloads ``app, nginx, consul, registrator`` from such as the example code on ``use-common.sh``.
```shell
app_image_name_in_registry="${git_image_load_from_host}/${git_image_load_from_pathname}-app:${git_image_version}"
nginx_image_name_in_registry="${git_image_load_from_host}/${git_image_load_from_pathname}-nginx:${git_image_version}"
Expand All @@ -563,16 +583,22 @@ sudo bash run-and-kill-jar-and-state-is-restarting-or-running.sh
git status # If any changes are detected, the source code may be corrupted.
```

### Structure

#### Use-[Module].sh
- Here, 'Use' is not related to Hooks commonly used in front-end frameworks like React. Instead, it is more similar to Traits in PHP."
### Concurrent Running for this App
- Running ```sudo bash *.sh``` concurrently for the **same** project at the same time, is NOT safe.
- Running ```sudo bash *.sh``` concurrently for **different** projects at the same time, is safe.
### Docker Swarm
- Beta version. which is supposed to be improved in v6.
- 'ORCHESTRATION_TYPE=stack' is currently experimental, keep 'ORCHESTRATION_TYPE=compose' as it is in the production stage.
- However, you would test the docker swarm, run the command. It is currently tested for the Java sample.
- ```shell
docker swarm init
sudo bash run.sh
```
---
---
2 changes: 1 addition & 1 deletion apply-security.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/bin/bash
set -eu

source ./util.sh
source use-common.sh
check_bash_version
check_gnu_grep_installed
check_gnu_sed_installed
Expand Down
2 changes: 1 addition & 1 deletion check-current-states.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/bin/bash
set -eu

source ./util.sh
source use-common.sh
check_bash_version
check_gnu_grep_installed
check_gnu_sed_installed
Expand Down
2 changes: 1 addition & 1 deletion check-source-integrity.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/bin/bash
set -eu

source ./util.sh
source use-common.sh
check_bash_version
check_gnu_grep_installed
check_gnu_sed_installed
Expand Down
1 change: 0 additions & 1 deletion docker-compose-app-nginx-original.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ services:
image: '${PROJECT_NAME}-nginx:latest'
restart: always
environment:
- TZ=Asia/Seoul
- SERVICE_NAME=nginx
env_file:
- .env
Expand Down
2 changes: 1 addition & 1 deletion emergency-consul-down-and-up.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/bin/bash
set -eu

source ./util.sh
source use-common.sh
check_bash_version
check_gnu_grep_installed
check_gnu_sed_installed
Expand Down
6 changes: 3 additions & 3 deletions emergency-nginx-down-and-up.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/bin/bash
set -eu

source ./util.sh
source use-common.sh

check_bash_version
check_gnu_grep_installed
Expand All @@ -20,7 +20,7 @@ source ./use-nginx.sh
cache_global_vars
check_env_integrity

# Eventually, it will be activated as 'state_a' in ./activate.sh, and unless specifically specified parameters as below,
# Eventually, it will be activated as 'state_a' in ./nginx-blue-green-nginx-blue-green-activate.sh, and unless specifically specified parameters as below,
# Nginx should be reconfigured with the existing state (from 'cache_global_vars').
state_a=${state_for_emergency}
state_b=${state_for_emergency}
Expand All @@ -40,4 +40,4 @@ echo "[NOTICE] Finally, !! Deploy the App as !! ${state_a} !!, we will now deplo
# run
nginx_down_and_up
# activate : blue or green
./activate.sh ${state_a} ${state_b} ${state_upstream} ${consul_key_value_store}
./nginx-blue-green-activate.sh ${state_a} ${state_b} ${state_upstream} ${consul_key_value_store}
8 changes: 4 additions & 4 deletions emergency-nginx-restart.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/bin/bash
set -eu

source ./util.sh
source use-common.sh
check_bash_version
check_gnu_grep_installed
check_gnu_sed_installed
Expand All @@ -15,12 +15,12 @@ git config core.filemode false
sleep 3

source ./use-nginx.sh
# Load necessary things from util.sh
# Load necessary things from use-common.sh

cache_global_vars
check_env_integrity

# Eventually, it will be activated as 'state_a' in ./activate.sh, and unless specifically specified parameters as below,
# Eventually, it will be activated as 'state_a' in ./nginx-blue-green-nginx-blue-green-activate.sh, and unless specifically specified parameters as below,
# Nginx should be reconfigured with the existing state (from 'cache_global_vars').
state_a=${state_for_emergency}
state_b=${state_for_emergency}
Expand Down Expand Up @@ -52,4 +52,4 @@ load_nginx_docker_image
# run
nginx_down_and_up
# activate : blue or green
./activate.sh ${state_a} ${state_b} ${state_upstream} ${consul_key_value_store}
./nginx-blue-green-activate.sh ${state_a} ${state_b} ${state_upstream} ${consul_key_value_store}
4 changes: 2 additions & 2 deletions activate.sh → nginx-blue-green-activate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# This is a private shell script. Do NOT use this directly.
set -eu

source ./util.sh
source use-common.sh
source ./use-app.sh

#cache_global_vars
Expand Down Expand Up @@ -99,7 +99,7 @@ while [ 1 ]; do
fi

if [[ ${is_run} == 'yes' ]]; then
./reset.sh ${consul_key_value_store} ${old_state} ${new_state}
./nginx-blue-green-reset.sh ${consul_key_value_store} ${old_state} ${new_state}
else
echo "[WARNING] We won't revert, as ${old_state} is NOT running as well."
fi
Expand Down
4 changes: 2 additions & 2 deletions reset.sh → nginx-blue-green-reset.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash
# This is a private shell script. Do NOT use this directly.
source ./util.sh
source use-common.sh

app_env=$(get_value_from_env "APP_ENV")
project_name=$(get_value_from_env "PROJECT_NAME")
Expand All @@ -10,7 +10,7 @@ consul_key_value_store=$1
state=$2
new_state=$3

echo "[NOTICE] Point Nginx back to ${state} from reset.sh."
echo "[NOTICE] Point Nginx back to ${state} from nginx-blue-green-reset.sh."
docker exec ${project_name}-nginx curl -X PUT -d ${state} ${consul_key_value_store} > /dev/null || {
echo "[ERROR] Setting ${state} on '/etc/nginx/conf.d/nginx.conf' directly according to the Nginx Contingency Plan."
docker exec ${project_name}-nginx cp -f /etc/consul-templates/nginx.conf.contingency.${state} /etc/nginx/conf.d/nginx.conf
Expand Down
Loading

0 comments on commit 3adc557

Please sign in to comment.