Skip to content

Commit

Permalink
feature : Track Git SHA for your container
Browse files Browse the repository at this point in the history
DOCKER_BUILD_SHA_INSERT_GIT_ROOT=

- Additionally, includes minor refactors
  • Loading branch information
patternhelloworld committed Nov 14, 2024
1 parent 776a3cf commit 2ba4d37
Show file tree
Hide file tree
Showing 24 changed files with 179 additions and 35 deletions.
3 changes: 3 additions & 0 deletions .env.example.local
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ GOOD_APP_HEALTH_CHECK_PATTERN=xxx
# This is for environment variables for docker-compose-app-${app_env}.
DOCKER_COMPOSE_ENVIRONMENT={"XDEBUG_CONFIG":"idekey=IDE_DEBUG","PHP_IDE_CONFIG":"serverName=laravel-crud-boilerplate"}
DOCKER_BUILD_ARGS={}
DOCKER_BUILD_LABELS=[]
DOCKER_BUILD_SHA_INSERT_GIT_ROOT=

DOCKER_COMPOSE_NGINX_SELECTIVE_VOLUMES=[]
DOCKER_COMPOSE_HOST_VOLUME_CHECK=false

Expand Down
3 changes: 3 additions & 0 deletions .env.example.real
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ GOOD_APP_HEALTH_CHECK_PATTERN=xxx
# This is for environment variables for docker-compose-app-${app_env}.
DOCKER_COMPOSE_ENVIRONMENT={}
DOCKER_BUILD_ARGS={}
DOCKER_BUILD_LABELS=[]
DOCKER_BUILD_SHA_INSERT_GIT_ROOT=

# This is overwritten on docker-compose-${project_name}-${app_env}.yml
DOCKER_COMPOSE_REAL_SELECTIVE_VOLUMES=[]
# This is added on docker-compose-${project_name}-nginx.yml
Expand Down
3 changes: 3 additions & 0 deletions .env.java.local
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ DOCKER_COMPOSE_ENVIRONMENT={"TZ":"Asia/Seoul"}
# This goes with "docker build ... in the 'run.sh' script file", and the command always contain "HOST_IP" and "APP_ENV" above.
# docker exec -it CONTAINER_NAME cat /var/log/env_build_args.log
DOCKER_BUILD_ARGS={"DOCKER_BUILDKIT":"1","PROJECT_ROOT_IN_CONTAINER":"/var/www/server/spring-sample-h-auth","APP_ENV":"local"}
DOCKER_BUILD_LABELS=[]
DOCKER_BUILD_SHA_INSERT_GIT_ROOT=

DOCKER_COMPOSE_NGINX_SELECTIVE_VOLUMES=[]
DOCKER_COMPOSE_HOST_VOLUME_CHECK=false

Expand Down
3 changes: 3 additions & 0 deletions .env.java.real
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ DOCKER_COMPOSE_ENVIRONMENT={"TZ":"Asia/Seoul"}
# This goes with "docker build ... in the 'run.sh' script file", and the command always contain "HOST_IP" and "APP_ENV" above.
# docker exec -it CONTAINER_NAME cat /var/log/env_build_args.log
DOCKER_BUILD_ARGS={"DOCKER_BUILDKIT":"1","PROJECT_ROOT_IN_CONTAINER":"/var/www/server/spring-sample-h-auth","APP_ENV":"production"}
DOCKER_BUILD_LABELS=["foo=happy","bar=sad"]
DOCKER_BUILD_SHA_INSERT_GIT_ROOT=

DOCKER_COMPOSE_REAL_SELECTIVE_VOLUMES=["./samples/spring-sample-h-auth/logs:/var/www/files"]
DOCKER_COMPOSE_NGINX_SELECTIVE_VOLUMES=["./shared/nginx-error-logs:/var/log/nginx"]
DOCKER_COMPOSE_HOST_VOLUME_CHECK=false
Expand Down
2 changes: 2 additions & 0 deletions .env.java.real.commercial.ssl.sample
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ DOCKER_COMPOSE_ENVIRONMENT={"TZ":"Asia/Seoul"}
# This goes with "docker build ... in the 'run.sh' script file", and the command always contain "HOST_IP" and "APP_ENV" above.
# 2) ''/var/web/project/spring-sample-h-auth' is here as well
DOCKER_BUILD_ARGS={"DOCKER_BUILDKIT":"1","PROJECT_ROOT_IN_CONTAINER":"/var/www/server/spring-sample-h-auth","FILE_STORAGE_ROOT_IN_CONTAINER":"/var/www/files","JVM_XMS":"2048","JVM_XMX":"4096"}
DOCKER_BUILD_LABELS=["foo.mylabel=happy","bar.mylabel=happy"]
DOCKER_BUILD_SHA_INSERT_GIT_ROOT=/var/www/server/spring-sample-h-auth

# 3) ''/var/web/project/spring-sample-h-auth' is here as well. The thing is you should locate 'application.properties', 'logback-spring.xml', 'yourdomain.com.jks' on the './src/main/resource' folder.
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"]
Expand Down
3 changes: 3 additions & 0 deletions .env.node.local
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ GOOD_APP_HEALTH_CHECK_PATTERN=docs
# This is for environment variables for docker-compose-app-${app_env}.
DOCKER_COMPOSE_ENVIRONMENT={"MONGODB_URL":"mongodb://host.docker.internal:27017/node-boilerplate","NODE_ENV":"development"}
DOCKER_BUILD_ARGS={}
DOCKER_BUILD_LABELS=["foo=happy","bar=sad"]
DOCKER_BUILD_SHA_INSERT_GIT_ROOT=

DOCKER_COMPOSE_NGINX_SELECTIVE_VOLUMES=[]
DOCKER_COMPOSE_HOST_VOLUME_CHECK=false

Expand Down
3 changes: 3 additions & 0 deletions .env.php.local
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ DOCKER_COMPOSE_ENVIRONMENT={"XDEBUG_CONFIG":"idekey=IDE_DEBUG","PHP_IDE_CONFIG":
# This goes with "docker build ... in the 'run.sh' script file", and the command always contain "HOST_IP" and "APP_ENV" above.
# docker exec -it CONTAINER_NAME cat /var/log/env_build_args.log
DOCKER_BUILD_ARGS={"SAMPLE":"YAHOO","SAMPLE2":"YAHOO2"}
DOCKER_BUILD_LABELS=["foo=happy","bar=sad"]
DOCKER_BUILD_SHA_INSERT_GIT_ROOT=

DOCKER_COMPOSE_NGINX_SELECTIVE_VOLUMES=[]
DOCKER_COMPOSE_HOST_VOLUME_CHECK=false

Expand Down
4 changes: 4 additions & 0 deletions .env.php.real
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ DOCKER_COMPOSE_ENVIRONMENT={"XDEBUG_CONFIG":"idekey=IDE_DEBUG","PHP_IDE_CONFIG":
# This goes with "docker build ... in the 'run.sh' script file", and the command always contain "HOST_IP" and "APP_ENV" above.
# docker exec -it CONTAINER_NAME cat /var/log/env_build_args.log
DOCKER_BUILD_ARGS={"SAMPLE":"YAHOO","SAMPLE2":"YAHOO2","shared_volume_group_id":"1351","shared_volume_group_name":"laravel-shared-volume-group"}
DOCKER_BUILD_LABELS=["foo=happy","bar=sad"]
# Your Git's commit SHA will be added as a label to DOCKER_BUILD_LABELS when your container is built.
DOCKER_BUILD_SHA_INSERT_GIT_ROOT=

# In the case of "REAL," the project is not synchronized in its entirety. The source codes that are required for only production are injected.
# For SSL, the host folder is recommended to be './.docker/ssl' to be synchronized with 'docker-compose-nginx-original.yml'
DOCKER_COMPOSE_REAL_SELECTIVE_VOLUMES=["./shared/app-error-logs:/var/www/app/storage/logs","./.docker/ssl:/etc/apache2/ssl"]
Expand Down
13 changes: 9 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

> One Simple Zero-Downtime Blue-Green Deployment with your Dockerfiles

## Table of Contents
- [Process Summary](#process-summary)
- [Features](#features)
Expand Down Expand Up @@ -31,7 +30,7 @@
- [Consul](#consul)
- [USE_NGINX_RESTRICTION on .env](#use_nginx_restriction-on-env)
- [Advanced](#advanced)
- [Gitlab Container Registry](#gitlab-container-registry)
- [GitLab Container Registry (Production)](#gitlab-container-registry-production)
- [Upload Image (CI/CD Server -> Git)](#upload-image-cicd-server---git)
- [Download Image (Git -> Production Server)](#download-image-git---production-server)
- [Extra Information](#extra-information)
Expand Down Expand Up @@ -80,7 +79,7 @@ graph TD;
```
![img5.png](/documents/images/img5.png)

![img6.png](documents/images/img6.png)
## Features

- **No Unpredictable Errors in Reverse Proxy and Deployment**
Expand Down Expand Up @@ -348,6 +347,10 @@ NGINX_RESTART=false
# Setting this to 'true' is not recommended for normal operation as it results in prolonged downtime.
CONSUL_RESTART=false
# Specify the location of the .git folder for your project here to enable tracking through container labels.
# To track, simply run `bash check-current_states.sh`.
DOCKER_BUILD_SHA_INSERT_GIT_ROOT=
# Not recommended for normal operation as it leads to a long downtime.
# If this is set to true, it entails running 'stop-all-containers.sh & remove-all-images.sh'.
# In case your project is renamed or moved to another folder, Docker may not work properly.
Expand Down Expand Up @@ -451,6 +454,8 @@ bash check-current-states.sh
[DEBUG] ! Checked which (Blue OR Green) is currently running... (Final Check) : blue_score : 130, green_score : 27, state : blue, new_state : green, state_for_emergency : blue, new_upstream : https://PROJECT_NAME:8300.
```
- The higher the score a state receives, the more likely it is to be the currently running state. So the updated App should be deployed as the non-occupied state(new_state).

- ![img6.png](documents/images/img6.png)

### Emergency
- Nginx (like when Nginx is NOT booted OR 502 error...)
Expand Down Expand Up @@ -542,7 +547,7 @@ bash check-source-integrity.sh
- ```bash run.sh```
## Gitlab Container Registry
## Gitlab Container Registry (Production)
### Upload Image (CI/CD Server -> Git)
- In case you run the command ``push-to-git.sh``, ``docker-blue-green-runner`` pushes one of ``Blue or Green`` images which is currently running to the address above of the Gitlab Container Registry.
Expand Down
2 changes: 2 additions & 0 deletions apply-security.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
set -eu

source use-common.sh

check_bash_version
check_gnu_grep_installed
check_gnu_sed_installed
check_yq_installed
check_git_docker_compose_commands_exist

cache_global_vars
Expand Down
18 changes: 17 additions & 1 deletion check-current-states.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,26 @@
set -eu

source use-common.sh

check_bash_version
check_gnu_grep_installed
check_gnu_sed_installed
check_yq_installed
check_git_docker_compose_commands_exist

# Load global variables
cache_global_vars

# Define container name
container_name="${project_name}-${state}"

echo "[NOTICE] Project Name: ${project_name}"
display_emphasized_message "[NOTICE] Current State: ${state}"
display_emphasized_message "[NOTICE] Container Name: ${container_name}"


# Call the function
display_emphasized_message "$(print_git_sha_and_message "$container_name" "$docker_build_sha_insert_git_root")"

cache_global_vars
# echo "[NOTICE] All labels inside the Container $container_name"
# docker inspect -f '{{json .Config.Labels}}' "$container_name" 2>/dev/null | yq -P
2 changes: 2 additions & 0 deletions check-source-integrity.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
set -eu

source use-common.sh

check_bash_version
check_gnu_grep_installed
check_gnu_sed_installed
check_yq_installed
check_git_docker_compose_commands_exist

git config apply.whitespace nowarn
Expand Down
2 changes: 1 addition & 1 deletion documents/Deploy-React-Project-with-DBGR.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@
NGINX_LOGROTATE_FILE_NUMBER=7
NGINX_LOGROTATE_FILE_SIZE=1M
# You can change the values below. These settings for security related to ``set-safe-permissions.sh`` at the root of Docker-Blue-Green-Runner.
# You can change the values below. These settings for security related to ``apply-security.sh`` at the root of Docker-Blue-Green-Runner.
SHARED_VOLUME_GROUP_ID=1559
SHARED_VOLUME_GROUP_NAME=mba-shared-volume-group
UIDS_BELONGING_TO_SHARED_VOLUME_GROUP_ID=1000,1001
Expand Down
Binary file added documents/images/img6.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion emergency-consul-down-and-up.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
set -eu

source use-common.sh
check_yq_installed

check_bash_version
check_gnu_grep_installed
check_gnu_sed_installed
check_yq_installed
check_git_docker_compose_commands_exist


Expand Down
2 changes: 1 addition & 1 deletion emergency-nginx-down-and-up.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ set -eu

source use-common.sh

check_yq_installed
check_bash_version
check_gnu_grep_installed
check_gnu_sed_installed
check_yq_installed
check_git_docker_compose_commands_exist

echo "[NOTICE] Substituting CRLF with LF to prevent possible CRLF errors..."
Expand Down
2 changes: 1 addition & 1 deletion emergency-nginx-restart.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ set -eu

source use-common.sh

check_yq_installed
check_bash_version
check_gnu_grep_installed
check_gnu_sed_installed
check_yq_installed
check_git_docker_compose_commands_exist

echo "[NOTICE] Substituting CRLF with LF to prevent possible CRLF errors..."
Expand Down
3 changes: 2 additions & 1 deletion remove-all-images.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
set -eu

source use-common.sh
check_yq_installed

check_bash_version
check_gnu_grep_installed
check_gnu_sed_installed
check_yq_installed
check_git_docker_compose_commands_exist

git config apply.whitespace nowarn
Expand Down
2 changes: 2 additions & 0 deletions rollback.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
set -eu

source use-common.sh

check_bash_version
check_gnu_grep_installed
check_gnu_sed_installed
check_yq_installed
check_git_docker_compose_commands_exist

sudo sed -i -e "s/\r$//g" $(basename $0)
Expand Down
22 changes: 16 additions & 6 deletions run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ display_checkpoint_message "Checking versions for supporting libraries...(1%)"
check_bash_version
check_gnu_grep_installed
check_gnu_sed_installed
check_yq_installed
check_git_docker_compose_commands_exist

check_yq_installed

sudo chmod a+x *.sh

Expand Down Expand Up @@ -195,8 +195,14 @@ _main() {
display_planned_transition "$initially_cached_old_state" "$new_state"
sleep 2

if [[ "${git_image_load_from}" == "build" && -n "${project_git_sha}" && -n "${docker_build_sha_insert_git_root}" ]]; then
commit_message=$(get_commit_message "$project_git_sha" "$docker_build_sha_insert_git_root")
display_checkpoint_message "Will build this GIT version: $project_git_sha : $commit_message"
sleep 1
fi

## App
display_checkpoint_message "Setting up the app configuration 'yml' for orchestration type: ${orchestration_type}... (5%)"
display_checkpoint_message "Setting up the app configuration 'yml' for orchestration type: ${orchestration_type}... (6%)"
initiate_docker_compose_file
apply_env_service_name_onto_app_yaml
apply_docker_compose_environment_onto_app_yaml
Expand Down Expand Up @@ -313,21 +319,25 @@ _main() {
echo "[NOTICE] For safety, finally check Consul pointing before stopping the previous container (${initially_cached_old_state})."
local consul_pointing=$(docker exec ${project_name}-nginx curl ${consul_key_value_store}?raw 2>/dev/null || echo "failed")
if [[ ${consul_pointing} != ${initially_cached_old_state} ]]; then

if [[ ${orchestration_type} != 'stack' ]]; then
docker-compose -f docker-${orchestration_type}-${project_name}-${app_env}.yml stop ${project_name}-${initially_cached_old_state}
echo "[NOTICE] The previous (${initially_cached_old_state}) container (initially_cached_old_state) has been stopped because the deployment was successful. (If NGINX_RESTART=true or CONSUL_RESTART=true, existing containers have already been terminated in the load_all_containers function.)"
else
docker stack rm ${project_name}-${initially_cached_old_state}
echo "[NOTICE] The previous (${initially_cached_old_state}) service (initially_cached_old_state) has been stopped because the deployment was successful. (If NGINX_RESTART=true or CONSUL_RESTART=true, existing containers have already been terminated in the load_all_containers function.)"
fi

display_checkpoint_message "CURRENT APP_URL: ${app_url}. Run 'bash check-current-states.sh' whenever you want to check the deployment status and Git SHA."
print_git_sha_and_message "${project_name}-${new_state}" "$docker_build_sha_insert_git_root"

echo "[NOTICE] Delete <none>:<none> images."
docker rmi $(docker images -f "dangling=true" -q) || echo "[NOTICE] Any images in use will not be deleted."

else
echo "[NOTICE] The previous (${initially_cached_old_state}) container (initially_cached_old_state) has NOT been stopped because the current Consul Pointing is ${consul_pointing}."
fi

echo "[NOTICE] Delete <none>:<none> images."
docker rmi $(docker images -f "dangling=true" -q) || echo "[NOTICE] Any images in use will not be deleted."

display_checkpoint_message "[NOTICE] APP_URL : ${app_url}"
}

_main
13 changes: 0 additions & 13 deletions set-safe-permissions.sh

This file was deleted.

3 changes: 2 additions & 1 deletion stop-all-containers.sh
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#!/bin/bash
source use-common.sh
check_yq_installed

check_bash_version
check_gnu_grep_installed
check_gnu_sed_installed
check_yq_installed
check_git_docker_compose_commands_exist

sudo sed -i -e "s/\r$//g" $(basename $0)
Expand Down
27 changes: 25 additions & 2 deletions use-app.sh
Original file line number Diff line number Diff line change
Expand Up @@ -153,14 +153,36 @@ load_app_docker_image() {
echo "[NOTICE] Build the image with ${docker_file_location}/${docker_file_name} (using cache)"
local env_build_args=$(make_docker_build_arg_strings)
echo "[NOTICE] DOCKER_BUILD_ARGS on the .env : ${env_build_args}"
echo "[NOTICE] DOCKER_BUILD_LABELS on the .env : ${docker_build_labels}"

# Convert DOCKER_BUILD_LABELS to Docker --label arguments
local label_args=""
IFS=',' read -r -a labels <<< "$docker_build_labels"

for label in "${labels[@]}"; do
# Ensure labels are in correct format (e.g., key=value)
formatted_label=$(echo "$label" | sed -e 's/^\[//' -e 's/\]$//' -e 's/^"//' -e 's/"$//' | xargs)

# Only add to label_args if formatted_label is not empty
if [[ -n "$formatted_label" ]]; then
label_args+="--label $formatted_label "
fi
done

# Trim whitespace and check if label_args is just "--label"
if [[ $(echo "$label_args" | xargs) == "--label" ]]; then
label_args=""
fi

echo "[NOTICE] Final DOCKER_BUILD_LABELS on the .env : ${label_args} "

if [[ ${docker_layer_corruption_recovery} == true ]]; then
echo "[NOTICE] Docker Build Command : docker build --no-cache --tag ${project_name}:latest --build-arg server="${app_env}" ${env_build_args} -f ${docker_file_name} -m ${docker_build_memory_usage} ."
cd ${docker_file_location} && docker build --no-cache --tag ${project_name}:latest --build-arg server="${app_env}" ${env_build_args} -f ${docker_file_name} -m ${docker_build_memory_usage} . || exit 1
cd ${docker_file_location} && docker build --no-cache --tag ${project_name}:latest ${label_args} --build-arg server="${app_env}" ${env_build_args} -f ${docker_file_name} -m ${docker_build_memory_usage} . || exit 1
cd -
else
echo "[NOTICE] Docker Build Command : docker build --build-arg DISABLE_CACHE=${CUR_TIME} --tag ${project_name}:latest --build-arg server="${app_env}" --build-arg HOST_IP="${HOST_IP}" ${env_build_args} -f ${docker_file_name} -m ${docker_build_memory_usage} ."
cd ${docker_file_location} && docker build --build-arg DISABLE_CACHE=${CUR_TIME} --tag ${project_name}:latest --build-arg server="${app_env}" --build-arg HOST_IP="${HOST_IP}" ${env_build_args} -f ${docker_file_name} -m ${docker_build_memory_usage} . || exit 1
cd ${docker_file_location} && docker build --build-arg DISABLE_CACHE=${CUR_TIME} --tag ${project_name}:latest ${label_args} --build-arg server="${app_env}" --build-arg HOST_IP="${HOST_IP}" ${env_build_args} -f ${docker_file_name} -m ${docker_build_memory_usage} . || exit 1
cd -
fi

Expand Down Expand Up @@ -273,6 +295,7 @@ check_availability_inside_container(){

echo "[NOTICE] [Internal Integrity Check : will deploy ${check_state}] In the ${container_name} Container, conduct the Connection Check (localhost:${app_port} --timeout=${2}). (If this is delayed, run ' docker logs -f ${container_name} (compose), docker service ps ${project_name}-${check_state}_${project_name}-${check_state} (stack) ' to check the status." >&2
echo "[NOTICE] [Internal Integrity Check : will deploy ${check_state}] Current status (inside Container) : \n $(docker logs ${container_name})" >&2
echo "[NOTICE] wait_for_it ( https://github.com/vishnubob/wait-for-it ) will do the Check" >&2
local wait_for_it_re=$(docker exec -w ${project_location} ${container_name} ./wait-for-it.sh localhost:${app_port} --timeout=${2}) || (echo "[ERROR] Failed in running (CONTAINER : ${project_location}/wait-for-it.sh)" >&2 && echo "false" && return)
if [[ $? != 0 ]]; then
echo "[ERROR] Failed in getting the correct return from wait-for-it.sh. (${wait_for_it_re})" >&2
Expand Down
Loading

0 comments on commit 2ba4d37

Please sign in to comment.