diff --git a/.gitea/workflows/ci-cd.yml b/.gitea/workflows/ci-cd.yml index b7af79e..951db2a 100644 --- a/.gitea/workflows/ci-cd.yml +++ b/.gitea/workflows/ci-cd.yml @@ -167,3 +167,46 @@ jobs: - name: Image summary run: | echo "Images pushed to git.dev.nii-ecos.ru/${{ github.repository_owner }}/" + + deploy: + name: Deploy to Server + runs-on: ubuntu-latest + needs: [push] + if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/dev' + + steps: + - name: Deploy via SSH + run: | + BRANCH_TAG=$(echo ${GITHUB_REF_NAME} | sed 's/\//-/g') + + # Setup SSH + mkdir -p ~/.ssh + echo "${DEPLOY_SSH_KEY}" > ~/.ssh/deploy_key + chmod 600 ~/.ssh/deploy_key + ssh-keyscan -H ${DEPLOY_HOST} >> ~/.ssh/known_hosts 2>/dev/null + + # Deploy commands + ssh -i ~/.ssh/deploy_key -o StrictHostKeyChecking=no ${DEPLOY_USER}@${DEPLOY_HOST} << EOF + cd /opt/mostovik-backend + + # Login to registry + echo "${REGISTRY_PASSWORD}" | docker login --username "${REGISTRY_USER}" --password-stdin git.dev.nii-ecos.ru + + # Pull new images + export IMAGE_TAG=${BRANCH_TAG} + docker compose -f docker-compose.prod.yml pull web celery_worker celery_beat + + # Restart services + docker compose -f docker-compose.prod.yml up -d web celery_worker celery_beat + + # Cleanup old images + docker image prune -f + EOF + + echo "Deployed ${BRANCH_TAG} to ${DEPLOY_HOST}" + env: + DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }} + DEPLOY_USER: ${{ secrets.DEPLOY_USER }} + DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }} + REGISTRY_USER: ${{ secrets.REGISTRY_USER }} + REGISTRY_PASSWORD: ${{ secrets.REGISTRY_TOKEN }} diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml new file mode 100644 index 0000000..b3b94a6 --- /dev/null +++ b/docker-compose.prod.yml @@ -0,0 +1,123 @@ +services: + db: + image: postgres:15.10 + container_name: mostovik_db + restart: unless-stopped + environment: + POSTGRES_DB: ${POSTGRES_DB} + POSTGRES_USER: ${POSTGRES_USER} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + volumes: + - ./data/db:/var/lib/postgresql/data + ports: + - "5432:5432" + networks: + - mostovik_network + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"] + interval: 30s + timeout: 10s + retries: 3 + + redis: + image: redis:7-alpine + container_name: mostovik_redis + restart: unless-stopped + ports: + - "6379:6379" + volumes: + - ./data/redis:/data + networks: + - mostovik_network + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 30s + timeout: 10s + retries: 3 + + web: + image: git.dev.nii-ecos.ru/avm/mostovik-web:${IMAGE_TAG:-dev} + container_name: mostovik_web + restart: unless-stopped + depends_on: + db: + condition: service_healthy + redis: + condition: service_healthy + environment: + - DEBUG=False + - SECRET_KEY=${SECRET_KEY} + - POSTGRES_HOST=db + - POSTGRES_PORT=5432 + - POSTGRES_DB=${POSTGRES_DB} + - POSTGRES_USER=${POSTGRES_USER} + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} + - REDIS_URL=redis://redis:6379/0 + - CELERY_BROKER_URL=redis://redis:6379/0 + - CELERY_RESULT_BACKEND=redis://redis:6379/0 + volumes: + - ./logs:/app/logs + - ./media:/app/media + - ./staticfiles:/app/staticfiles + ports: + - "8000:8000" + networks: + - mostovik_network + command: > + sh -c "python src/manage.py migrate && + python src/manage.py collectstatic --noinput && + gunicorn config.wsgi:application --bind 0.0.0.0:8000 --workers 3" + + celery_worker: + image: git.dev.nii-ecos.ru/avm/mostovik-celery:${IMAGE_TAG:-dev} + container_name: mostovik_celery_worker + restart: unless-stopped + depends_on: + db: + condition: service_healthy + redis: + condition: service_healthy + environment: + - DEBUG=False + - POSTGRES_HOST=db + - POSTGRES_PORT=5432 + - POSTGRES_DB=${POSTGRES_DB} + - POSTGRES_USER=${POSTGRES_USER} + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} + - REDIS_URL=redis://redis:6379/0 + - CELERY_BROKER_URL=redis://redis:6379/0 + - CELERY_RESULT_BACKEND=redis://redis:6379/0 + volumes: + - ./logs:/app/logs + networks: + - mostovik_network + command: celery -A config worker --loglevel=info + + celery_beat: + image: git.dev.nii-ecos.ru/avm/mostovik-celery:${IMAGE_TAG:-dev} + container_name: mostovik_celery_beat + restart: unless-stopped + depends_on: + db: + condition: service_healthy + redis: + condition: service_healthy + environment: + - DEBUG=False + - POSTGRES_HOST=db + - POSTGRES_PORT=5432 + - POSTGRES_DB=${POSTGRES_DB} + - POSTGRES_USER=${POSTGRES_USER} + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} + - REDIS_URL=redis://redis:6379/0 + - CELERY_BROKER_URL=redis://redis:6379/0 + - CELERY_RESULT_BACKEND=redis://redis:6379/0 + volumes: + - ./logs:/app/logs + networks: + - mostovik_network + command: celery -A config beat --loglevel=info --scheduler django_celery_beat.schedulers:DatabaseScheduler + +networks: + mostovik_network: + driver: bridge