feat: deploy
This commit is contained in:
parent
f8e1e89a83
commit
c536dcb623
|
|
@ -5,14 +5,9 @@ on:
|
||||||
branches: ["main"]
|
branches: ["main"]
|
||||||
|
|
||||||
env:
|
env:
|
||||||
REGISTRY: gitea.leonmorival.com
|
KAMAL_IMAGE: ghcr.io/basecamp/kamal:v2.11.0
|
||||||
IMAGE_NAME: daily_meal/bemeal-api
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
# =========================
|
|
||||||
# TESTS
|
|
||||||
# =========================
|
|
||||||
test:
|
test:
|
||||||
name: Tests Unitaires
|
name: Tests Unitaires
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
@ -31,13 +26,10 @@ jobs:
|
||||||
with:
|
with:
|
||||||
args: >
|
args: >
|
||||||
bash -c "composer install --no-interaction --ignore-platform-req=ext-intl
|
bash -c "composer install --no-interaction --ignore-platform-req=ext-intl
|
||||||
&& php artisan test"
|
&& php artisan test --compact"
|
||||||
|
|
||||||
# =========================
|
deploy:
|
||||||
# BUILD & PUSH
|
name: Deploy with Kamal
|
||||||
# =========================
|
|
||||||
build:
|
|
||||||
name: Build & Push Docker
|
|
||||||
needs: test
|
needs: test
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
|
@ -45,61 +37,84 @@ jobs:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Login to Gitea Registry
|
- name: Prepare SSH agent
|
||||||
run: |
|
|
||||||
echo "${{ secrets.TOKEN_GITEA }}" \
|
|
||||||
| docker login $REGISTRY \
|
|
||||||
-u "${{ github.actor }}" \
|
|
||||||
--password-stdin
|
|
||||||
|
|
||||||
- name: Build & Push image
|
|
||||||
run: |
|
|
||||||
IMAGE=$REGISTRY/$IMAGE_NAME
|
|
||||||
docker build -t "$IMAGE:${{ github.sha }}" -t "$IMAGE:latest" .
|
|
||||||
docker push "$IMAGE:${{ github.sha }}"
|
|
||||||
docker push "$IMAGE:latest"
|
|
||||||
|
|
||||||
# =========================
|
|
||||||
# DEPLOY (SIMPLE)
|
|
||||||
# =========================
|
|
||||||
deploy:
|
|
||||||
name: Deploy
|
|
||||||
needs: build
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Deploy via SSH
|
|
||||||
uses: appleboy/ssh-action@v1.0.3
|
|
||||||
env:
|
env:
|
||||||
IMAGE_TAG: ${{ github.sha }}
|
SSH_HOST: ${{ secrets.SSH_HOST }}
|
||||||
REGISTRY: gitea.leonmorival.com
|
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||||
IMAGE_NAME: daily_meal/bemeal-api
|
run: |
|
||||||
with:
|
set -eu
|
||||||
host: ${{ secrets.SSH_HOST }}
|
|
||||||
username: ${{ secrets.SSH_USER }}
|
|
||||||
key: ${{ secrets.SSH_PRIVATE_KEY }}
|
|
||||||
envs: IMAGE_TAG,REGISTRY,IMAGE_NAME
|
|
||||||
script: |
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
APP_DIR="/opt/bemeal"
|
eval "$(ssh-agent -s)"
|
||||||
cd "$APP_DIR"
|
echo "SSH_AUTH_SOCK=$SSH_AUTH_SOCK" >> "$GITHUB_ENV"
|
||||||
|
|
||||||
COMPOSE="docker compose \
|
printf '%s\n' "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
|
||||||
--project-directory $APP_DIR \
|
|
||||||
--env-file $APP_DIR/.env.prod \
|
|
||||||
-f $APP_DIR/docker-compose.prod.yml"
|
|
||||||
|
|
||||||
IMAGE="$REGISTRY/$IMAGE_NAME:$IMAGE_TAG"
|
mkdir -p ~/.ssh
|
||||||
|
chmod 700 ~/.ssh
|
||||||
|
ssh-keyscan -H "${SSH_HOST:-89.167.35.217}" >> ~/.ssh/known_hosts
|
||||||
|
|
||||||
echo "Pull image"
|
- name: Prepare Kamal network
|
||||||
docker pull "$IMAGE"
|
env:
|
||||||
|
SSH_HOST: ${{ secrets.SSH_HOST }}
|
||||||
|
SSH_USER: ${{ secrets.SSH_USER }}
|
||||||
|
run: |
|
||||||
|
set -eu
|
||||||
|
|
||||||
echo "Start infra services"
|
REMOTE_HOST="${SSH_HOST:-89.167.35.217}"
|
||||||
$COMPOSE up -d pgsql redis meilisearch
|
REMOTE_USER="${SSH_USER:-root}"
|
||||||
|
|
||||||
echo "Deploy API (blue/green handled by Caddy)"
|
ssh "$REMOTE_USER@$REMOTE_HOST" <<'EOF'
|
||||||
IMAGE="$IMAGE" $COMPOSE up -d --no-deps --force-recreate bemeal-api-blue
|
set -eu
|
||||||
IMAGE="$IMAGE" $COMPOSE up -d --no-deps --force-recreate bemeal-api-green
|
|
||||||
|
|
||||||
echo "Deployment done"
|
docker network inspect kamal >/dev/null 2>&1 || docker network create kamal
|
||||||
|
|
||||||
|
for container in bemeal-pgsql bemeal-redis bemeal-meilisearch bemeal-adminer; do
|
||||||
|
if docker inspect "$container" >/dev/null 2>&1; then
|
||||||
|
docker network connect kamal "$container" >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
EOF
|
||||||
|
|
||||||
|
- name: Write Kamal secrets
|
||||||
|
run: |
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
mkdir -p .kamal
|
||||||
|
cat > .kamal/secrets <<'EOF'
|
||||||
|
GITEA_TOKEN=$GITEA_TOKEN
|
||||||
|
APP_KEY=$APP_KEY
|
||||||
|
DB_DATABASE=$DB_DATABASE
|
||||||
|
DB_USERNAME=$DB_USERNAME
|
||||||
|
DB_PASSWORD=$DB_PASSWORD
|
||||||
|
MEILISEARCH_KEY=$MEILISEARCH_KEY
|
||||||
|
EOF
|
||||||
|
chmod 600 .kamal/secrets
|
||||||
|
|
||||||
|
- name: Deploy
|
||||||
|
env:
|
||||||
|
GITEA_TOKEN: ${{ secrets.TOKEN_GITEA }}
|
||||||
|
APP_KEY: ${{ secrets.APP_KEY }}
|
||||||
|
DB_DATABASE: ${{ secrets.DB_DATABASE }}
|
||||||
|
DB_USERNAME: ${{ secrets.DB_USERNAME }}
|
||||||
|
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
|
||||||
|
MEILISEARCH_KEY: ${{ secrets.MEILISEARCH_KEY }}
|
||||||
|
SSH_HOST: ${{ secrets.SSH_HOST }}
|
||||||
|
SSH_USER: ${{ secrets.SSH_USER }}
|
||||||
|
run: |
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
docker run --rm \
|
||||||
|
-v "$PWD:/workdir" \
|
||||||
|
-v "$SSH_AUTH_SOCK:/ssh-agent" \
|
||||||
|
-v "$HOME/.ssh:/root/.ssh:ro" \
|
||||||
|
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||||
|
-e SSH_AUTH_SOCK=/ssh-agent \
|
||||||
|
-e GITEA_TOKEN \
|
||||||
|
-e APP_KEY \
|
||||||
|
-e DB_DATABASE \
|
||||||
|
-e DB_USERNAME \
|
||||||
|
-e DB_PASSWORD \
|
||||||
|
-e MEILISEARCH_KEY \
|
||||||
|
-e SSH_HOST \
|
||||||
|
-e SSH_USER \
|
||||||
|
"$KAMAL_IMAGE" deploy
|
||||||
|
|
|
||||||
|
|
@ -23,3 +23,4 @@ Homestead.json
|
||||||
Homestead.yaml
|
Homestead.yaml
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
.env.prod
|
.env.prod
|
||||||
|
.kamal/secrets
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
echo "Docker set up on $KAMAL_HOSTS..."
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
echo "Booted app version $KAMAL_VERSION on $KAMAL_HOSTS..."
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# A sample post-deploy hook
|
||||||
|
#
|
||||||
|
# These environment variables are available:
|
||||||
|
# KAMAL_RECORDED_AT
|
||||||
|
# KAMAL_PERFORMER
|
||||||
|
# KAMAL_VERSION
|
||||||
|
# KAMAL_HOSTS
|
||||||
|
# KAMAL_ROLES (if set)
|
||||||
|
# KAMAL_DESTINATION (if set)
|
||||||
|
# KAMAL_RUNTIME
|
||||||
|
|
||||||
|
echo "$KAMAL_PERFORMER deployed $KAMAL_VERSION to $KAMAL_DESTINATION in $KAMAL_RUNTIME seconds"
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
echo "Rebooted kamal-proxy on $KAMAL_HOSTS"
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
echo "Booting app version $KAMAL_VERSION on $KAMAL_HOSTS..."
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# A sample pre-build hook
|
||||||
|
#
|
||||||
|
# Checks:
|
||||||
|
# 1. We have a clean checkout
|
||||||
|
# 2. A remote is configured
|
||||||
|
# 3. The branch has been pushed to the remote
|
||||||
|
# 4. The version we are deploying matches the remote
|
||||||
|
#
|
||||||
|
# These environment variables are available:
|
||||||
|
# KAMAL_RECORDED_AT
|
||||||
|
# KAMAL_PERFORMER
|
||||||
|
# KAMAL_VERSION
|
||||||
|
# KAMAL_HOSTS
|
||||||
|
# KAMAL_ROLES (if set)
|
||||||
|
# KAMAL_DESTINATION (if set)
|
||||||
|
|
||||||
|
if [ -n "$(git status --porcelain)" ]; then
|
||||||
|
echo "Git checkout is not clean, aborting..." >&2
|
||||||
|
git status --porcelain >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
first_remote=$(git remote)
|
||||||
|
|
||||||
|
if [ -z "$first_remote" ]; then
|
||||||
|
echo "No git remote set, aborting..." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
current_branch=$(git branch --show-current)
|
||||||
|
|
||||||
|
if [ -z "$current_branch" ]; then
|
||||||
|
echo "Not on a git branch, aborting..." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
remote_head=$(git ls-remote $first_remote --tags $current_branch | cut -f1)
|
||||||
|
|
||||||
|
if [ -z "$remote_head" ]; then
|
||||||
|
echo "Branch not pushed to remote, aborting..." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$KAMAL_VERSION" != "$remote_head" ]; then
|
||||||
|
echo "Version ($KAMAL_VERSION) does not match remote HEAD ($remote_head), aborting..." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
#!/usr/bin/env ruby
|
||||||
|
|
||||||
|
# A sample pre-connect check
|
||||||
|
#
|
||||||
|
# Warms DNS before connecting to hosts in parallel
|
||||||
|
#
|
||||||
|
# These environment variables are available:
|
||||||
|
# KAMAL_RECORDED_AT
|
||||||
|
# KAMAL_PERFORMER
|
||||||
|
# KAMAL_VERSION
|
||||||
|
# KAMAL_HOSTS
|
||||||
|
# KAMAL_ROLES (if set)
|
||||||
|
# KAMAL_DESTINATION (if set)
|
||||||
|
# KAMAL_RUNTIME
|
||||||
|
|
||||||
|
hosts = ENV["KAMAL_HOSTS"].split(",")
|
||||||
|
results = nil
|
||||||
|
max = 3
|
||||||
|
|
||||||
|
elapsed = Benchmark.realtime do
|
||||||
|
results = hosts.map do |host|
|
||||||
|
Thread.new do
|
||||||
|
tries = 1
|
||||||
|
|
||||||
|
begin
|
||||||
|
Socket.getaddrinfo(host, 0, Socket::AF_UNSPEC, Socket::SOCK_STREAM, nil, Socket::AI_CANONNAME)
|
||||||
|
rescue SocketError
|
||||||
|
if tries < max
|
||||||
|
puts "Retrying DNS warmup: #{host}"
|
||||||
|
tries += 1
|
||||||
|
sleep rand
|
||||||
|
retry
|
||||||
|
else
|
||||||
|
puts "DNS warmup failed: #{host}"
|
||||||
|
host
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
tries
|
||||||
|
end
|
||||||
|
end.map(&:value)
|
||||||
|
end
|
||||||
|
|
||||||
|
retries = results.sum - hosts.size
|
||||||
|
nopes = results.count { |r| r == max }
|
||||||
|
|
||||||
|
puts "Prewarmed %d DNS lookups in %.2f sec: %d retries, %d failures" % [ hosts.size, elapsed, retries, nopes ]
|
||||||
|
|
@ -0,0 +1,122 @@
|
||||||
|
#!/usr/bin/env ruby
|
||||||
|
|
||||||
|
# A sample pre-deploy hook
|
||||||
|
#
|
||||||
|
# Checks the Github status of the build, waiting for a pending build to complete for up to 720 seconds.
|
||||||
|
#
|
||||||
|
# Fails unless the combined status is "success"
|
||||||
|
#
|
||||||
|
# These environment variables are available:
|
||||||
|
# KAMAL_RECORDED_AT
|
||||||
|
# KAMAL_PERFORMER
|
||||||
|
# KAMAL_VERSION
|
||||||
|
# KAMAL_HOSTS
|
||||||
|
# KAMAL_COMMAND
|
||||||
|
# KAMAL_SUBCOMMAND
|
||||||
|
# KAMAL_ROLES (if set)
|
||||||
|
# KAMAL_DESTINATION (if set)
|
||||||
|
|
||||||
|
# Only check the build status for production deployments
|
||||||
|
if ENV["KAMAL_COMMAND"] == "rollback" || ENV["KAMAL_DESTINATION"] != "production"
|
||||||
|
exit 0
|
||||||
|
end
|
||||||
|
|
||||||
|
require "bundler/inline"
|
||||||
|
|
||||||
|
# true = install gems so this is fast on repeat invocations
|
||||||
|
gemfile(true, quiet: true) do
|
||||||
|
source "https://rubygems.org"
|
||||||
|
|
||||||
|
gem "octokit"
|
||||||
|
gem "faraday-retry"
|
||||||
|
end
|
||||||
|
|
||||||
|
MAX_ATTEMPTS = 72
|
||||||
|
ATTEMPTS_GAP = 10
|
||||||
|
|
||||||
|
def exit_with_error(message)
|
||||||
|
$stderr.puts message
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
|
||||||
|
class GithubStatusChecks
|
||||||
|
attr_reader :remote_url, :git_sha, :github_client, :combined_status
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
@remote_url = github_repo_from_remote_url
|
||||||
|
@git_sha = `git rev-parse HEAD`.strip
|
||||||
|
@github_client = Octokit::Client.new(access_token: ENV["GITHUB_TOKEN"])
|
||||||
|
refresh!
|
||||||
|
end
|
||||||
|
|
||||||
|
def refresh!
|
||||||
|
@combined_status = github_client.combined_status(remote_url, git_sha)
|
||||||
|
end
|
||||||
|
|
||||||
|
def state
|
||||||
|
combined_status[:state]
|
||||||
|
end
|
||||||
|
|
||||||
|
def first_status_url
|
||||||
|
first_status = combined_status[:statuses].find { |status| status[:state] == state }
|
||||||
|
first_status && first_status[:target_url]
|
||||||
|
end
|
||||||
|
|
||||||
|
def complete_count
|
||||||
|
combined_status[:statuses].count { |status| status[:state] != "pending"}
|
||||||
|
end
|
||||||
|
|
||||||
|
def total_count
|
||||||
|
combined_status[:statuses].count
|
||||||
|
end
|
||||||
|
|
||||||
|
def current_status
|
||||||
|
if total_count > 0
|
||||||
|
"Completed #{complete_count}/#{total_count} checks, see #{first_status_url} ..."
|
||||||
|
else
|
||||||
|
"Build not started..."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def github_repo_from_remote_url
|
||||||
|
url = `git config --get remote.origin.url`.strip.delete_suffix(".git")
|
||||||
|
if url.start_with?("https://github.com/")
|
||||||
|
url.delete_prefix("https://github.com/")
|
||||||
|
elsif url.start_with?("git@github.com:")
|
||||||
|
url.delete_prefix("git@github.com:")
|
||||||
|
else
|
||||||
|
url
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
$stdout.sync = true
|
||||||
|
|
||||||
|
begin
|
||||||
|
puts "Checking build status..."
|
||||||
|
|
||||||
|
attempts = 0
|
||||||
|
checks = GithubStatusChecks.new
|
||||||
|
|
||||||
|
loop do
|
||||||
|
case checks.state
|
||||||
|
when "success"
|
||||||
|
puts "Checks passed, see #{checks.first_status_url}"
|
||||||
|
exit 0
|
||||||
|
when "failure"
|
||||||
|
exit_with_error "Checks failed, see #{checks.first_status_url}"
|
||||||
|
when "pending"
|
||||||
|
attempts += 1
|
||||||
|
end
|
||||||
|
|
||||||
|
exit_with_error "Checks are still pending, gave up after #{MAX_ATTEMPTS * ATTEMPTS_GAP} seconds" if attempts == MAX_ATTEMPTS
|
||||||
|
|
||||||
|
puts checks.current_status
|
||||||
|
sleep(ATTEMPTS_GAP)
|
||||||
|
checks.refresh!
|
||||||
|
end
|
||||||
|
rescue Octokit::NotFound
|
||||||
|
exit_with_error "Build status could not be found"
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
echo "Rebooting kamal-proxy on $KAMAL_HOSTS..."
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
service: bemeal
|
||||||
|
image: daily_meal/bemeal-api
|
||||||
|
|
||||||
|
x-hosts: &hosts
|
||||||
|
- <%= ENV.fetch("SSH_HOST", "89.167.35.217") %>
|
||||||
|
|
||||||
|
servers:
|
||||||
|
web:
|
||||||
|
hosts: *hosts
|
||||||
|
horizon:
|
||||||
|
hosts: *hosts
|
||||||
|
cmd: php artisan horizon
|
||||||
|
scheduler:
|
||||||
|
hosts: *hosts
|
||||||
|
cmd: php artisan schedule:work
|
||||||
|
|
||||||
|
proxy:
|
||||||
|
host: bemeal.leonmorival.com
|
||||||
|
ssl: true
|
||||||
|
app_port: 80
|
||||||
|
healthcheck:
|
||||||
|
path: /up
|
||||||
|
|
||||||
|
registry:
|
||||||
|
server: gitea.leonmorival.com
|
||||||
|
username: leon.morival@gmail.com
|
||||||
|
password:
|
||||||
|
- GITEA_TOKEN
|
||||||
|
|
||||||
|
ssh:
|
||||||
|
user: <%= ENV.fetch("SSH_USER", "root") %>
|
||||||
|
|
||||||
|
builder:
|
||||||
|
arch: amd64
|
||||||
|
|
||||||
|
env:
|
||||||
|
clear:
|
||||||
|
APP_LOCALE: fr
|
||||||
|
APP_ENV: production
|
||||||
|
APP_DEBUG: "false"
|
||||||
|
APP_URL: https://bemeal.leonmorival.com
|
||||||
|
SERVER_NAME: ":80"
|
||||||
|
APP_RUNTIME: "Laravel\\FrankenPHP\\Runtime"
|
||||||
|
FILESYSTEM_DISK: public
|
||||||
|
DB_CONNECTION: pgsql
|
||||||
|
DB_HOST: bemeal-pgsql
|
||||||
|
DB_PORT: "5432"
|
||||||
|
REDIS_HOST: bemeal-redis
|
||||||
|
REDIS_CLIENT: predis
|
||||||
|
QUEUE_CONNECTION: redis
|
||||||
|
SCOUT_DRIVER: meilisearch
|
||||||
|
MEILISEARCH_HOST: http://bemeal-meilisearch:7700
|
||||||
|
secret:
|
||||||
|
- APP_KEY
|
||||||
|
- DB_DATABASE
|
||||||
|
- DB_USERNAME
|
||||||
|
- DB_PASSWORD
|
||||||
|
- MEILISEARCH_KEY
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- bemeal_storage_data:/var/www/html/storage/app
|
||||||
|
- bemeal_storage_public_data:/var/www/html/storage/app/public
|
||||||
|
|
||||||
|
aliases:
|
||||||
|
artisan: app exec --reuse "php artisan"
|
||||||
|
shell: app exec --interactive --reuse "sh"
|
||||||
|
|
@ -1,105 +1,6 @@
|
||||||
name: bemeal
|
name: bemeal
|
||||||
|
|
||||||
# =========================
|
|
||||||
# IMAGE
|
|
||||||
# =========================
|
|
||||||
x-app-image: &app-image gitea.leonmorival.com/daily_meal/bemeal-api:${IMAGE_TAG:-latest}
|
|
||||||
|
|
||||||
# =========================
|
|
||||||
# ENV
|
|
||||||
# =========================
|
|
||||||
x-app-environment: &app-environment
|
|
||||||
APP_LOCALE: "fr"
|
|
||||||
APP_ENV: "production"
|
|
||||||
APP_KEY: "${APP_KEY:?APP_KEY is required}"
|
|
||||||
APP_URL: "${APP_URL:?APP_URL is required}"
|
|
||||||
SERVER_NAME: ":80"
|
|
||||||
APP_RUNTIME: "Laravel\\FrankenPHP\\Runtime"
|
|
||||||
APP_DEBUG: "${APP_DEBUG:-false}"
|
|
||||||
|
|
||||||
FILESYSTEM_DISK: "public"
|
|
||||||
|
|
||||||
DB_CONNECTION: "pgsql"
|
|
||||||
DB_HOST: "bemeal-pgsql"
|
|
||||||
DB_PORT: "5432"
|
|
||||||
DB_DATABASE: "${DB_DATABASE:?DB_DATABASE is required}"
|
|
||||||
DB_USERNAME: "${DB_USERNAME:?DB_USERNAME is required}"
|
|
||||||
DB_PASSWORD: "${DB_PASSWORD:?DB_PASSWORD is required}"
|
|
||||||
|
|
||||||
REDIS_HOST: "bemeal-redis"
|
|
||||||
REDIS_CLIENT: "predis"
|
|
||||||
QUEUE_CONNECTION: "redis"
|
|
||||||
|
|
||||||
SCOUT_DRIVER: "meilisearch"
|
|
||||||
MEILISEARCH_HOST: "http://bemeal-meilisearch:7700"
|
|
||||||
MEILISEARCH_KEY: "${MEILISEARCH_KEY:?MEILISEARCH_KEY is required}"
|
|
||||||
|
|
||||||
# =========================
|
|
||||||
# VOLUMES
|
|
||||||
# =========================
|
|
||||||
x-app-volumes: &app-volumes
|
|
||||||
- storage-data:/var/www/html/storage/app
|
|
||||||
- storage-public-data:/var/www/html/storage/app/public
|
|
||||||
|
|
||||||
# =========================
|
|
||||||
# DEPENDS
|
|
||||||
# =========================
|
|
||||||
x-app-depends-on: &app-depends-on
|
|
||||||
pgsql:
|
|
||||||
condition: service_healthy
|
|
||||||
redis:
|
|
||||||
condition: service_started
|
|
||||||
meilisearch:
|
|
||||||
condition: service_started
|
|
||||||
|
|
||||||
# =========================
|
|
||||||
# HEALTHCHECK
|
|
||||||
# =========================
|
|
||||||
x-app-healthcheck: &app-healthcheck
|
|
||||||
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1/api/health >/dev/null 2>&1"]
|
|
||||||
start_period: 30s
|
|
||||||
interval: 5s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 12
|
|
||||||
|
|
||||||
# =========================
|
|
||||||
# APP BASE
|
|
||||||
# =========================
|
|
||||||
x-app-service: &app-service
|
|
||||||
image: *app-image
|
|
||||||
restart: unless-stopped
|
|
||||||
depends_on: *app-depends-on
|
|
||||||
environment: *app-environment
|
|
||||||
volumes: *app-volumes
|
|
||||||
networks:
|
|
||||||
- internal
|
|
||||||
- public
|
|
||||||
stop_grace_period: 30s
|
|
||||||
|
|
||||||
# =========================
|
|
||||||
# SERVICES
|
|
||||||
# =========================
|
|
||||||
services:
|
services:
|
||||||
|
|
||||||
# =========================
|
|
||||||
# BLUE
|
|
||||||
# =========================
|
|
||||||
bemeal-api-blue:
|
|
||||||
<<: *app-service
|
|
||||||
container_name: bemeal-api-blue
|
|
||||||
healthcheck: *app-healthcheck
|
|
||||||
|
|
||||||
# =========================
|
|
||||||
# GREEN
|
|
||||||
# =========================
|
|
||||||
bemeal-api-green:
|
|
||||||
<<: *app-service
|
|
||||||
container_name: bemeal-api-green
|
|
||||||
healthcheck: *app-healthcheck
|
|
||||||
|
|
||||||
# =========================
|
|
||||||
# DATABASE
|
|
||||||
# =========================
|
|
||||||
pgsql:
|
pgsql:
|
||||||
image: postgres:15-alpine
|
image: postgres:15-alpine
|
||||||
container_name: bemeal-pgsql
|
container_name: bemeal-pgsql
|
||||||
|
|
@ -117,11 +18,8 @@ services:
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 10
|
retries: 10
|
||||||
networks:
|
networks:
|
||||||
- internal
|
- kamal
|
||||||
|
|
||||||
# =========================
|
|
||||||
# REDIS
|
|
||||||
# =========================
|
|
||||||
redis:
|
redis:
|
||||||
image: redis:alpine
|
image: redis:alpine
|
||||||
container_name: bemeal-redis
|
container_name: bemeal-redis
|
||||||
|
|
@ -129,47 +27,8 @@ services:
|
||||||
volumes:
|
volumes:
|
||||||
- redis-data:/data
|
- redis-data:/data
|
||||||
networks:
|
networks:
|
||||||
- internal
|
- kamal
|
||||||
|
|
||||||
# =========================
|
|
||||||
# HORIZON
|
|
||||||
# =========================
|
|
||||||
horizon:
|
|
||||||
image: *app-image
|
|
||||||
container_name: bemeal-horizon
|
|
||||||
restart: unless-stopped
|
|
||||||
depends_on:
|
|
||||||
pgsql:
|
|
||||||
condition: service_healthy
|
|
||||||
redis:
|
|
||||||
condition: service_started
|
|
||||||
environment: *app-environment
|
|
||||||
volumes: *app-volumes
|
|
||||||
command: php artisan horizon
|
|
||||||
networks:
|
|
||||||
- internal
|
|
||||||
|
|
||||||
# =========================
|
|
||||||
# SCHEDULER
|
|
||||||
# =========================
|
|
||||||
scheduler:
|
|
||||||
image: *app-image
|
|
||||||
container_name: bemeal-scheduler
|
|
||||||
restart: unless-stopped
|
|
||||||
depends_on:
|
|
||||||
pgsql:
|
|
||||||
condition: service_healthy
|
|
||||||
redis:
|
|
||||||
condition: service_started
|
|
||||||
environment: *app-environment
|
|
||||||
volumes: *app-volumes
|
|
||||||
command: php artisan schedule:work
|
|
||||||
networks:
|
|
||||||
- internal
|
|
||||||
|
|
||||||
# =========================
|
|
||||||
# ADMINER
|
|
||||||
# =========================
|
|
||||||
adminer:
|
adminer:
|
||||||
image: adminer:latest
|
image: adminer:latest
|
||||||
container_name: bemeal-adminer
|
container_name: bemeal-adminer
|
||||||
|
|
@ -177,11 +36,8 @@ services:
|
||||||
environment:
|
environment:
|
||||||
ADMINER_DEFAULT_SERVER: bemeal-pgsql
|
ADMINER_DEFAULT_SERVER: bemeal-pgsql
|
||||||
networks:
|
networks:
|
||||||
- internal
|
- kamal
|
||||||
|
|
||||||
# =========================
|
|
||||||
# MEILISEARCH
|
|
||||||
# =========================
|
|
||||||
meilisearch:
|
meilisearch:
|
||||||
image: getmeili/meilisearch:latest
|
image: getmeili/meilisearch:latest
|
||||||
container_name: bemeal-meilisearch
|
container_name: bemeal-meilisearch
|
||||||
|
|
@ -192,11 +48,8 @@ services:
|
||||||
volumes:
|
volumes:
|
||||||
- meilisearch-data:/meili_data
|
- meilisearch-data:/meili_data
|
||||||
networks:
|
networks:
|
||||||
- internal
|
- kamal
|
||||||
|
|
||||||
# =========================
|
|
||||||
# VOLUMES
|
|
||||||
# =========================
|
|
||||||
volumes:
|
volumes:
|
||||||
pgsql-data:
|
pgsql-data:
|
||||||
external: true
|
external: true
|
||||||
|
|
@ -205,23 +58,10 @@ volumes:
|
||||||
redis-data:
|
redis-data:
|
||||||
name: bemeal_redis_data
|
name: bemeal_redis_data
|
||||||
|
|
||||||
storage-data:
|
|
||||||
name: bemeal_storage_data
|
|
||||||
|
|
||||||
storage-public-data:
|
|
||||||
name: bemeal_storage_public_data
|
|
||||||
|
|
||||||
meilisearch-data:
|
meilisearch-data:
|
||||||
name: bemeal_meilisearch_data
|
name: bemeal_meilisearch_data
|
||||||
|
|
||||||
# =========================
|
|
||||||
# NETWORKS
|
|
||||||
# =========================
|
|
||||||
networks:
|
networks:
|
||||||
internal:
|
kamal:
|
||||||
name: bemeal_internal
|
|
||||||
driver: bridge
|
|
||||||
|
|
||||||
public:
|
|
||||||
external: true
|
external: true
|
||||||
name: bemeal_public
|
name: kamal
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue