Tip
Now works with Docker Compose. No Swarm Required!
mode: compose
. See Inputs for more details...
This action deploys a docker stack from a compose file to a remote docker host using SSH Password or Key File Authentication. You can also optionally authenticate against a private registry using a username and password.
This action uses a remote docker context to deploy the stack from the working directory allowing you to easily prepare the workspace for deployment.
Portainer Users: You can deploy directly to Portainer with: cssnr/portainer-stack-deploy-action
Note
Please submit a Feature Request for new features or Open an Issue if you find any bugs.
For more details see action.yaml and src/main.sh.
Input Name | Is Required | Default Value | Input Description |
---|---|---|---|
name |
Yes | - | Docker Stack/Project Name * |
file |
- | docker-compose.yaml |
Docker Stack/Compose File |
mode ¹ |
- | swarm |
Deploy Mode: [swarm , compose ] * |
args ¹ |
- | --remove-orphans --force-recreate |
Additional Arguments for Compose * |
host |
Yes | - | Remote Docker Hostname or IP * |
port |
- | 22 |
Remote Docker Port |
user |
Yes | - | Remote Docker Username |
pass |
or ssh_key |
- | Remote Docker Password * |
ssh_key |
or pass |
- | Remote SSH Key File * |
env_file |
- | - | Docker Environment File * |
detach ² |
- | true |
Detach Flag, false , to disable * |
prune ² |
- | false |
Prune Flag, true , to enable |
resolve_image ² |
- | always |
Resolve [always , changed , never ] * |
registry_auth ² |
- | - | Enable Registry Authentication * |
registry_host |
- | - | Registry Authentication Host * |
registry_user |
- | - | Registry Authentication Username * |
registry_pass |
- | - | Registry Authentication Password * |
summary |
- | true |
Add Job Summary * |
¹ Compose Only, view the Docs.
² Swarm Only, view the Docs.
* More details below...
📟 Click Here to see how the deployment command is generated
if [[ "${INPUT_MODE}" == "swarm" ]];then
DEPLOY_TYPE="Swarm"
COMMAND=("docker" "stack" "deploy" "-c" "${INPUT_FILE}" "${EXTRA_ARGS[@]}" "${INPUT_NAME}")
else
DEPLOY_TYPE="Compose"
COMMAND=("docker" "compose" "-f" "${INPUT_FILE}" "-p" "${INPUT_NAME}" "up" "-d" "-y" "${EXTRA_ARGS[@]}")
fi
name: Stack name for Swarm and project name for Compose.
mode: Compose only. Set this to compose
to use compose up
instead of stack deploy
for non-swarm hosts.
args: Compose only. Compose arguments to pass to the compose up
command. Only used for mode: compose
deployments.
The detach
flag defaults to false for compose. With no args the default is --remove-orphans --force-recreate
.
Use an empty string to override. For more details, see the compose
docs.
host: The hostname or IP address of the remote docker server to deploy too. If your hostname is behind a proxy like Cloudflare you will need to use the IP address.
pass/ssh_key: You must provide either a pass
or ssh_key
, not both.
env_file: Variables in this file are exported before running stack deploy.
To use a docker env_file
specify it in your compose file and make it available in a previous step.
If you need compose file templating this can also be done in a previous step.
If using mode: compose
you can also add the compose_arg: --env-file stringArray
.
detach: Swarm only. Set this to false
to not exit immediately and wait for the services to converge.
This will generate extra output in the logs and is useful for debugging deployments.
Defaults to false
in mode: compose
.
resolve_image: Swarm only. When the default always
is used, this argument is omitted.
registry_auth: Swarm only. Set to true
to deploy with --with-registry-auth
.
registry_host: To run docker login
on another registry. Example: ghcr.io
.
registry_user/registry_pass: Required to run docker login
before stack deploy.
summary: Write a Summary for the job. To disable this set to false
.
To view a workflow run, click on a recent Test job (requires login).
👀 View Example Successful ✔️ Job Summary
🚀 Swarm Stack test_stack-deploy
Successfully Deployed.
docker stack deploy -c docker-compose.yaml --detach=false --resolve-image=changed test_stack-deploy
Results
Updating service test_stack-deploy_alpine (id: tdk8v42m0rvp9hz4rbfrtszb6)
1/1:
overall progress: 0 out of 1 tasks
overall progress: 1 out of 1 tasks
verify: Waiting 5 seconds to verify that tasks are stable...
verify: Waiting 4 seconds to verify that tasks are stable...
verify: Waiting 3 seconds to verify that tasks are stable...
verify: Waiting 2 seconds to verify that tasks are stable...
verify: Waiting 1 seconds to verify that tasks are stable...
verify: Service tdk8v42m0rvp9hz4rbfrtszb6 converged
👀 View Example Failure ❌ Job Summary
⛔ Swarm Stack test_stack-deploy
Failed to Deploy!
docker stack deploy -c docker-compose.yaml --detach=false --resolve-image=changed test_stack-deploy
Errors
Creating network test_stack-deploy_default
failed to create network test_stack-deploy_default: Error response from daemon: network with name test_stack-deploy_default already exists
- name: 'Stack Deploy'
uses: cssnr/stack-deploy-action@v1
with:
name: 'stack-name'
file: 'docker-compose-swarm.yaml'
host: ${{ secrets.DOCKER_HOST }}
port: ${{ secrets.DOCKER_PORT }}
user: ${{ secrets.DOCKER_USER }}
pass: ${{ secrets.DOCKER_PASS }} # not needed with ssh_key
ssh_key: ${{ secrets.DOCKER_SSH_KEY }} # not needed with pass
💡 Click on an example heading to expand or collapse the example.
With Password, docker login and --with-registry-auth
- name: 'Stack Deploy'
uses: cssnr/stack-deploy-action@v1
with:
name: 'stack-name'
file: 'docker-compose-swarm.yaml'
host: ${{ secrets.DOCKER_HOST }}
port: ${{ secrets.DOCKER_PORT }}
user: ${{ secrets.DOCKER_USER }}
pass: ${{ secrets.DOCKER_PASS }}
registry_host: 'ghcr.io'
registry_user: ${{ vars.GHCR_USER }}
registry_pass: ${{ secrets.GHCR_PASS }}
With SSH Key, --prune, --detach=false and --resolve-image=changed
- name: 'Stack Deploy'
uses: cssnr/stack-deploy-action@v1
with:
name: 'stack-name'
file: 'docker-compose-swarm.yaml'
host: ${{ secrets.DOCKER_HOST }}
port: ${{ secrets.DOCKER_PORT }}
user: ${{ secrets.DOCKER_USER }}
ssh_key: ${{ secrets.DOCKER_SSH_KEY }}
detach: false
prune: true
resolve_image: 'changed'
With All Swarm Inputs
- name: 'Stack Deploy'
uses: cssnr/stack-deploy-action@v1
with:
name: 'stack-name'
file: 'docker-compose-swarm.yaml'
host: ${{ secrets.DOCKER_HOST }}
port: ${{ secrets.DOCKER_PORT }}
user: ${{ secrets.DOCKER_USER }}
pass: ${{ secrets.DOCKER_PASS }} # not needed with ssh_key
ssh_key: ${{ secrets.DOCKER_SSH_KEY }} # not needed with pass
env_file: 'stack.env'
detach: true
prune: false
resolve_image: 'always'
registry_auth: true # not needed with registry_pass/registry_user
registry_host: 'ghcr.io'
registry_user: ${{ vars.GHCR_USER }}
registry_pass: ${{ secrets.GHCR_PASS }}
summary: true
Compose with Defaults
- name: 'Compose Deploy'
uses: cssnr/stack-deploy-action@v1
with:
name: 'stack-name'
file: 'docker-compose.yaml'
host: ${{ secrets.DOCKER_HOST }}
port: ${{ secrets.DOCKER_PORT }}
user: ${{ secrets.DOCKER_USER }}
ssh_key: ${{ secrets.DOCKER_SSH_KEY }}
mode: compose
Compose with Custom Arguments
- name: 'Compose Deploy'
uses: cssnr/stack-deploy-action@v1
with:
name: 'stack-name'
file: 'docker-compose.yaml'
host: ${{ secrets.DOCKER_HOST }}
port: ${{ secrets.DOCKER_PORT }}
user: ${{ secrets.DOCKER_USER }}
ssh_key: ${{ secrets.DOCKER_SSH_KEY }}
mode: compose
args: --remove-orphans --force-recreate
Note: these are the default arguments. If you use args
this will override the default arguments unless they are included.
You can disable them by passing an empty string. For more details, see the compose up docs.
Compose with Private Image
- name: 'Compose Deploy'
uses: cssnr/stack-deploy-action@v1
with:
name: 'stack-name'
file: 'docker-compose.yaml'
host: ${{ secrets.DOCKER_HOST }}
port: ${{ secrets.DOCKER_PORT }}
user: ${{ secrets.DOCKER_USER }}
ssh_key: ${{ secrets.DOCKER_SSH_KEY }}
registry_host: 'ghcr.io'
registry_user: ${{ vars.GHCR_USER }}
registry_pass: ${{ secrets.GHCR_PASS }}
mode: compose
With All Compose Inputs
- name: 'Stack Deploy'
uses: cssnr/stack-deploy-action@v1
with:
name: 'stack-name'
file: 'docker-compose-swarm.yaml'
host: ${{ secrets.DOCKER_HOST }}
port: ${{ secrets.DOCKER_PORT }}
user: ${{ secrets.DOCKER_USER }}
pass: ${{ secrets.DOCKER_PASS }} # not needed with ssh_key
ssh_key: ${{ secrets.DOCKER_SSH_KEY }} # not needed with pass
env_file: 'stack.env'
registry_host: 'ghcr.io'
registry_user: ${{ vars.GHCR_USER }}
registry_pass: ${{ secrets.GHCR_PASS }}
mode: compose
args: --remove-orphans --force-recreate
summary: true
Simple Workflow Example
name: 'Stack Deploy Action'
on:
push:
jobs:
deploy:
name: 'Deploy'
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: 'Checkout'
uses: actions/checkout@v4
- name: 'Stack Deploy'
uses: cssnr/stack-deploy-action@v1
with:
name: 'stack-name'
file: 'docker-compose-swarm.yaml'
host: ${{ secrets.DOCKER_HOST }}
port: ${{ secrets.DOCKER_PORT }}
user: ${{ secrets.DOCKER_USER }}
pass: ${{ secrets.DOCKER_PASS }}
Full Workflow Example
name: 'Stack Deploy Action'
on:
workflow_dispatch:
inputs:
tags:
description: 'Tags: comma,separated'
required: true
default: 'latest'
env:
REGISTRY: 'ghcr.io'
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: true
jobs:
build:
name: 'Build'
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
packages: write
steps:
- name: 'Checkout'
uses: actions/checkout@v4
- name: 'Setup Buildx'
uses: docker/setup-buildx-action@v2
with:
platforms: 'linux/amd64,linux/arm64'
- name: 'Docker Login'
uses: docker/login-action@v3
with:
registry: $${{ env.REGISTRY }}
username: ${{ secrets.GHCR_USER }}
password: ${{ secrets.GHCR_PASS }}
- name: 'Generate Tags'
id: tags
uses: cssnr/docker-tags-action@v1
with:
images: $${{ env.REGISTRY }}/${{ github.repository }}
tags: ${{ inputs.tags }}
- name: 'Build and Push'
uses: docker/build-push-action@v6
with:
context: .
platforms: 'linux/amd64,linux/arm64'
push: true
tags: ${{ steps.tags.outputs.tags }}
labels: ${{ steps.tags.outputs.labels }}
deploy:
name: 'Deploy'
runs-on: ubuntu-latest
timeout-minutes: 5
needs: [build]
steps:
- name: 'Checkout'
uses: actions/checkout@v4
- name: 'Stack Deploy'
uses: cssnr/stack-deploy-action@v1
with:
name: 'stack-name'
file: 'docker-compose-swarm.yaml'
host: ${{ secrets.DOCKER_HOST }}
port: ${{ secrets.DOCKER_PORT }}
user: ${{ secrets.DOCKER_USER }}
ssh_key: ${{ secrets.DOCKER_SSH_KEY }}
cleanup:
name: 'Cleanup'
runs-on: ubuntu-latest
timeout-minutes: 5
needs: deploy
permissions:
contents: read
packages: write
steps:
- name: 'Purge Cache'
uses: cssnr/cloudflare-purge-cache-action@v2
with:
token: ${{ secrets.CLOUDFLARE_API_TOKEN }}
zones: cssnr.com
For more examples, you can check out other projects using this action:
https://github.com/cssnr/stack-deploy-action/network/dependents
The following rolling tags are maintained.
Version Tag | Rolling | Bugs | Feat. | Name | Target | Example |
---|---|---|---|---|---|---|
✅ | ✅ | ✅ | Major | vN.x.x |
vN |
|
✅ | ✅ | ❌ | Minor | vN.N.x |
vN.N |
|
❌ | ❌ | ❌ | Micro | vN.N.N |
vN.N.N |
You can view the release notes for each version on the releases page.
The Major tag is recommended. It is the most up-to-date and always backwards compatible. Breaking changes would result in a Major version bump. At a minimum you should use a Minor tag.
- Deploy to a remote host using SSH or Password authentication.
- Deploy using a remote context from the current working directory.
- Deploy from a compose file to either a Docker Swarm or Compose host.
- Displays output in logs, captures it in the Summary, and checks the status.
- Allows logging into a private registry and deploying with registry auth.
- Allows specifying all arguments for both Swarm and Compose deployments.
Don't see your feature here? Request it below in the Support section.
For general help or to request a feature see:
- Q&A Discussion: https://github.com/cssnr/stack-deploy-action/discussions/categories/q-a
- Request a Feature: https://github.com/cssnr/stack-deploy-action/discussions/categories/feature-requests
If you are experiencing an issue/bug or getting unexpected results you can:
- Report an Issue: https://github.com/cssnr/stack-deploy-action/issues
- Chat with us on Discord: https://discord.gg/wXy6m2X8wY
- Provide General Feedback: https://cssnr.github.io/feedback/
For more information, see the CSSNR SUPPORT.md.
Currently, the best way to contribute to this project is to star this project on GitHub.
If you would like to submit a PR, please review the CONTRIBUTING.md.
Additionally, you can support other GitHub Actions I have published:
- Stack Deploy Action
- Portainer Stack Deploy
- VirusTotal Action
- Mirror Repository Action
- Update Version Tags Action
- Update JSON Value Action
- Parse Issue Form Action
- Cloudflare Purge Cache Action
- Mozilla Addon Update Action
- Docker Tags Action
For a full list of current projects to support visit: https://cssnr.github.io/