Created
November 22, 2024 21:01
-
-
Save kamaroly/e0dd5f9fe3dd9776df814288b7faf418 to your computer and use it in GitHub Desktop.
I use these batch script to achieve Zero-deployment for phoenix application with releases without docker.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Exit immediately if a command exits with a non-zero status | |
set -e | |
SCRIPT_PATH=$(dirname "$(realpath "$0")") | |
BUILD_PATH=$SCRIPT_PATH"/.." | |
# Change directory to build path | |
cd $BUILD_PATH | |
# Function to display an error and exit | |
function error_exit { | |
echo "Error: $1" | |
exit 1 | |
} | |
# Step 1: Fetch production dependencies | |
echo "1. Fetching production dependencies..." | |
mix deps.get --only prod || error_exit "Failed to fetch dependencies." | |
# Step 2: Compile the application in production environment | |
echo "2. Compiling the application for production..." | |
MIX_ENV=prod mix compile || error_exit "Compilation failed." | |
# Step 3: Deploy assets | |
echo "3. Deploying assets..." | |
# setopt rm_star_silent # Disable prompt for delete confirmation | |
# Remove previously compiled assets | |
rm -rf priv/static/* | |
MIX_ENV=prod mix assets.deploy || error_exit "Asset deployment failed." | |
# Step 4: Generate the release | |
echo "Generating the Phoenix release..." | |
mix phx.gen.release || error_exit "Failed to generate the Phoenix release." | |
# Step 5: Build the release | |
echo "Building the release..." | |
yes | MIX_ENV=prod mix release || error_exit "Release build failed." | |
echo "Release build completed successfully!" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
your-domain.com { | |
reverse_proxy localhost:4010 localhost:4020 localhost:4030 localhost:4040 localhost:4050 localhost:4060 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Initialize variables | |
PORTS=("4010" "4020" "4030" "4040" "4050" "4060") # Default ports for zero-downtime deployment | |
USERNAME="postgres" | |
PASSWORD="ikijumba" | |
HOST="localhost" | |
DATABASE="hr_dev" | |
APP_NAME="hr" | |
MODE="daemon_iex" | |
# It's important for this to be static. It will be needed to restart apps/ releases. | |
SECRET_KEY="J1k3ARebfz5+zTGI5Uc4Z4gy6F6XxCJXN3V10dNiOIP1joQcExncj9JsQeQcsaYg" | |
SCRIPT_PATH=$(dirname "$(realpath "$0")") | |
BUILD_PATH="/home/kamaro/elixir/hr/_build/prod/rel/hr" | |
# Change directory to build path | |
cd $BUILD_PATH | |
# Change to the directory with the app for release | |
cd $BUILD_PATH | |
# Parse named parameters | |
while [[ $# -gt 0 ]]; do | |
case $1 in | |
--ports) | |
IFS=',' read -ra PORTS <<< "$2" # Split comma-separated ports into an array | |
shift 2 | |
;; | |
--username) | |
USERNAME=$2 | |
shift 2 | |
;; | |
--password) | |
PASSWORD=$2 | |
shift 2 | |
;; | |
--host) | |
HOST=$2 | |
shift 2 | |
;; | |
--database) | |
DATABASE=$2 | |
shift 2 | |
;; | |
--app-name) | |
APP_NAME=$2 | |
shift 2 | |
;; | |
--build-path) | |
BUILD_PATH=$2 | |
shift 2 | |
;; | |
--secret-key) | |
SECRET_KEY=$2 | |
shift 2 | |
;; | |
--mode) | |
MODE=$2 | |
shift 2 | |
;; | |
*) | |
echo "Unknown option: $1" | |
exit 1 | |
;; | |
esac | |
done | |
# Check if all required parameters are provided | |
if [ -z "$PORTS" ] || [ -z "$USERNAME" ] || [ -z "$PASSWORD" ] || [ -z "$HOST" ] || [ -z "$DATABASE" ] || [ -z "$APP_NAME" ] || [ -z "$BUILD_PATH" ] || [ -z "$SECRET_KEY" ]; then | |
echo "Error: Missing required parameters." | |
echo "Usage: $0 --ports <port1,port2,...> --username <username> --password <password> --host <host> --database <database> --app-name <app_name> --build-path <build_path> --secret-key <secret_key>" | |
exit 1 | |
fi | |
# Export required environment variables | |
export SECRET_KEY_BASE=$SECRET_KEY | |
export DATABASE_URL=ecto://$USERNAME:$PASSWORD@$HOST/$DATABASE | |
# Function to check if a port is responding | |
function is_port_responding() { | |
local PORT=$1 | |
for i in {1..30}; do | |
if nc -z localhost $PORT; then | |
echo "Port $PORT is responding!" | |
return 0 | |
fi | |
echo "Waiting for port $PORT to respond... (attempt $i)" | |
sleep 1 | |
done | |
echo "Port $PORT did not respond in time." | |
return 1 | |
} | |
# To Achieve Zero-downtime deployment, we need to have multiple instances of the same application on different port, then | |
# restart them in sequences. Since caddy is handling reverse proxy/ load balancing, it will automatically respond to the | |
# available port. See card configurations. | |
for PORT in "${PORTS[@]}"; do | |
echo "Stopping existing app_$PORT on port $PORT (if running)..." | |
RELEASE_NODE=app_$PORT PORT=$PORT $BUILD_PATH/bin/$APP_NAME stop || echo "No running instance on port $PORT" | |
echo "Restarting app_$PORT on port $PORT..." | |
RELEASE_NODE=app_$PORT PORT=$PORT $BUILD_PATH/bin/$APP_NAME daemon | |
echo "Checking if instance on port $PORT is responding..." | |
if ! is_port_responding $PORT; then | |
echo "Failed to start app_$PORT on port $PORT Aborting." | |
exit 1 | |
fi | |
done | |
echo "Zero-downtime deployment complete. Running on ports: ${PORTS[*]}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
SCRIPT_PATH=$(dirname "$(realpath "$0")") | |
BUILD_PATH=$SCRIPT_PATH"/.." | |
PRODUCTION_SERVER_HOST="SERVER_IP_ADDRESS" | |
PRODUCTION_USER="root" | |
APP_ENV="prod" | |
APP_NAME="hr" | |
echo "1. Zipping release into $APP_NAME.tar.gz..." | |
tar -czf $APP_NAME.tar.gz -C $BUILD_PATH/_build/${APP_ENV}/rel/$APP_NAME . | |
echo "2. Moving $APP_NAME.tar.gz to production server..." | |
scp $APP_NAME.tar.gz $PRODUCTION_USER@$PRODUCTION_SERVER_HOST:~/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment