diff --git a/.github/workflows/deploy-docker.yml b/.github/workflows/deploy-docker.yml new file mode 100644 index 0000000..eff55eb --- /dev/null +++ b/.github/workflows/deploy-docker.yml @@ -0,0 +1,122 @@ +name: Build & Deploy Docker + +on: + workflow_call: + inputs: + dockerfile: + description: "Path to Dockerfile" + default: "Dockerfile" + required: false + type: string + image_name: + description: "Full image name (e.g. org/my-api)" + required: true + type: string + image_tag: + description: "Optional tag override (defaults to pushed Git tag)" + required: false + type: string + remote_host: + description: "SSH host (user@host)" + required: true + type: string + remote_path: + description: "Remote path where compose files live" + required: true + type: string + runner_group: + description: "Runner group or label" + required: false + default: "ubuntu-latest" + type: string + secrets: + dockerhub_username: + required: true + dockerhub_password: + required: true + ssh_private_key: + required: true + outputs: + tag: + description: "Tag effectively built/deployed" + value: ${{ jobs.get-tag.outputs.tag }} + +permissions: + id-token: write + contents: read + +jobs: + get-tag: + runs-on: ${{ inputs.runner_group }} + outputs: + tag: ${{ steps.out.outputs.tag }} + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Compute tag + id: out + run: | + TAG="${{ inputs.image_tag }}" + if [ -z "$TAG" ]; then + TAG="${GITHUB_REF##*/}" # refs/tags/v1.2.3 → v1.2.3 + fi + echo "tag=$TAG" >> "$GITHUB_OUTPUT" + + build: + needs: get-tag + uses: iExecBlockchainComputing/github-actions-workflows/.github/workflows/docker-build.yml@docker-build-v2.2.0 + with: + dockerfile: ${{ inputs.dockerfile }} + image-name: ${{ inputs.image_name }} + image-tag: ${{ needs.get-tag.outputs.tag }} + hadolint: false + security-scan: false + push: true + secrets: + username: ${{ secrets.dockerhub_username }} + password: ${{ secrets.dockerhub_password }} + + deploy: + needs: [build, get-tag] + runs-on: ${{ inputs.runner_group }} + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Install SSH key + uses: webfactory/ssh-agent@v0.9.0 + with: + ssh-private-key: ${{ secrets.ssh_private_key }} + + - name: Add remote host to known_hosts + run: ssh-keyscan -H "${{ inputs.remote_host#*@ }}" >> ~/.ssh/known_hosts + + - name: Prepare .env for Compose + run: | + cat < .env +IMAGE_NAME=${{ inputs.image_name }} +IMAGE_TAG=${{ needs.get-tag.outputs.tag }} +DOCKERHUB_USERNAME=${{ secrets.dockerhub_username }} +DOCKERHUB_PASSWORD=${{ secrets.dockerhub_password }} +EOF + + - name: Copy compose files + run: | + scp docker-compose.yml .env "${{ inputs.remote_host }}":"${{ inputs.remote_path }}/" + + - name: Pull & restart containers + run: | + ssh "${{ inputs.remote_host }}" bash -s <<'REMOTE' + cd "${{ inputs.remote_path }}" + set -e + export \$(grep -v '^#' .env | xargs) + echo "$DOCKERHUB_PASSWORD" | docker login -u "$DOCKERHUB_USERNAME" --password-stdin + docker compose pull + docker compose up -d +REMOTE diff --git a/README.md b/README.md index 12df42d..f7201a5 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,9 @@ This repository contains a comprehensive collection of reusable GitHub Actions w ### 🐳 [Build Docker Image](./docker-build) Automates the process of building, tagging, and pushing Docker images to Docker Hub. Perfect for projects that require containerization with minimal configuration overhead. +### 🚀 [Deploy Docker](./deploy-docker) +Automates the process of building a Docker image and deploying it to a remote server. Configurable for different Dockerfile paths, image names, tags, and remote hosts. Streamlines the deployment process with secure SSH connections. + ### 📦 [Release Please](./release-please) Uses the [release-please-action](https://github.com/googleapis/release-please-action) to automate versioning and changelog generation based on Conventional Commits. This workflow streamlines your release process and ensures consistent version management. diff --git a/deploy-docker/CHANGELOG.md b/deploy-docker/CHANGELOG.md new file mode 100644 index 0000000..e69de29 diff --git a/deploy-docker/README.md b/deploy-docker/README.md new file mode 100644 index 0000000..515363d --- /dev/null +++ b/deploy-docker/README.md @@ -0,0 +1,124 @@ +# Docker Build & Deploy - Reusable Workflow Documentation 🚀 + +## Overview 🌟 + +This reusable GitHub Actions workflow automates the process of building a Docker image and deploying it to a remote server. It is configurable via inputs for the Dockerfile path, image name, tag, remote host, and other options. The workflow performs the following actions: + +- **Determines the Tag**: Computes the tag to use for the Docker image. 🏷️ +- **Builds the Docker Image**: Builds and pushes the Docker image to DockerHub. 🔨 +- **Deploys to Remote Server**: Securely deploys the image to a remote server using SSH. 🚀 + +## Workflow Inputs 🛠️ + +| **Input** | **Description** | **Required** | **Default** | +|------------------|-----------------------------------------------------|--------------|-----------------| +| **dockerfile** | Path to Dockerfile. | No | `Dockerfile` | +| **image_name** | Full image name (e.g. org/my-api). | Yes | - | +| **image_tag** | Optional tag override (defaults to pushed Git tag). | No | - | +| **remote_host** | SSH host (user@host). | Yes | - | +| **remote_path** | Remote path where compose files live. | Yes | - | +| **runner_group** | Runner group or label. | No | `ubuntu-latest` | + +### Secrets 🔐 + +| **Secret** | **Description** | **Required** | +|------------------------|----------------------------------------|--------------| +| **dockerhub_username** | DockerHub username for authentication. | Yes | +| **dockerhub_password** | DockerHub password for authentication. | Yes | +| **ssh_private_key** | SSH private key for remote deployment. | Yes | + +### Outputs 📤 + +| **Output** | **Description** | **Value** | +|------------|--------------------------------|-----------------------------------| +| **tag** | Tag effectively built/deployed | `${{ jobs.get-tag.outputs.tag }}` | + +## Jobs and Steps ⚙️ + +### Job: `get-tag` +- **Purpose**: Determines the tag to use for the Docker image. +- **Runs On**: The specified runner group (default: `ubuntu-latest`). +- **Steps**: + 1. Checkout the repository. + 2. Compute the tag (uses the provided tag or extracts it from the Git reference). + +### Job: `build` +- **Purpose**: Builds and pushes the Docker image. +- **Depends On**: `get-tag` +- **Uses**: The docker-build workflow from the same repository. +- **Inputs**: + - Dockerfile path + - Image name and tag + - Push configuration (set to true) + +### Job: `deploy` +- **Purpose**: Deploys the Docker image to a remote server. +- **Depends On**: `build` and `get-tag` +- **Runs On**: The specified runner group. +- **Steps**: + 1. Checkout the repository. + 2. Install SSH key for secure connection. + 3. Add remote host to known_hosts. + 4. Prepare .env file for Docker Compose. + 5. Copy compose files to the remote server. + 6. Pull and restart containers on the remote server. + +## How to Use This Reusable Workflow 🔄 + +1. **Save the Workflow File** + This workflow is already saved as `.github/workflows/deploy-docker.yml` in the repository. 💾 + +2. **Call the Reusable Workflow** + In another workflow file (e.g., triggered by a release), invoke this reusable workflow like so: + + ```yaml + name: Deploy My Docker Application + on: + release: + types: [published] + + jobs: + deploy: + uses: iExecBlockchainComputing/github-actions-workflows/.github/workflows/deploy-docker.yml@main + with: + dockerfile: 'path/to/Dockerfile' + image_name: 'your-org/your-app' + remote_host: 'user@your-server.com' + remote_path: '/path/to/deployment' + secrets: + dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} + dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} + ssh_private_key: ${{ secrets.SSH_PRIVATE_KEY }} + ``` + +3. **Configure Secrets** + Ensure that the following secrets are added to your repository's settings: + - `DOCKERHUB_USERNAME`: Your DockerHub username + - `DOCKERHUB_PASSWORD`: Your DockerHub password or access token + - `SSH_PRIVATE_KEY`: The SSH private key for connecting to the remote server + +## Prerequisites 📋 + +1. **Docker Compose File**: + - You must have a `docker-compose.yml` file in the root of your repository. + - This file should reference the environment variables `IMAGE_NAME` and `IMAGE_TAG`. + +2. **Remote Server**: + - The remote server must have Docker and Docker Compose installed. + - The user specified in `remote_host` must have permissions to run Docker commands. + +## Workflow Steps in Detail 🔍 + +1. **Get Tag**: + - Checks out the repository. + - Computes the tag to use (either from the input or from the Git reference). + +2. **Build Docker Image**: + - Uses the docker-build workflow to build and push the Docker image. + - Configures the image with the computed tag. + +3. **Deploy to Remote Server**: + - Sets up SSH authentication. + - Prepares the environment variables file. + - Copies the necessary files to the remote server. + - Pulls the latest image and restarts the containers using Docker Compose. \ No newline at end of file diff --git a/deploy-docker/version.txt b/deploy-docker/version.txt new file mode 100644 index 0000000..e69de29 diff --git a/publish-npm/README.md b/publish-npm/README.md index 584b4b6..f90a28a 100644 --- a/publish-npm/README.md +++ b/publish-npm/README.md @@ -74,7 +74,7 @@ for the package scope, Node.js version, registry URL, and other options. The wor jobs: publish: - uses: your-org/your-repo/.github/workflows/publish-npm.yml@main + uses: iExecBlockchainComputing/github-actions-workflows/.github/workflows/publish-npm.yml@main with: node-version: '22' build-command: 'npm run build:prod'