I prefer using Ansible to manage my servers, and for my apps, I opt for Docker Swarm. To me, Docker Swarm strikes a good balance between the complexity of Kubernetes and the challenges of creating my own zero-downtime deployment script. Notably, I utilize it only on a single node, which eliminates a lot of potential complexity.
Ansible features a docker_stack module, so let’s delve into how to utilize it:
- Before initiating any deployment, ensure that all essential directories and configurations are properly set up.
- Use Ansible templates to generate the stack file and then upload it to the host.
- I like to pre-pull the required Docker images for the services. This ensures they are immediately available for deployment. Even though the stack deploy would pull the image if needed, having this as a separate step provides certainty that the image is present.
- With all prerequisites met, deploy the services to Docker Swarm (
prune
will ensure removing services that are not in stack file)
- name: Create directories if they don't exist
file:
path: "{{ item }}"
state: directory
owner: root
group: root
mode: 0775
loop:
- /opt/swarm
- /opt/swarm/data
- /opt/swarm/data/traefik
- /opt/swarm/data/letsencrypt
- name: Create stack file
ansible.builtin.template:
src: templates/stackfile.yml.j2
dest: "/opt/swarm/stack.yml"
- name: Pull an image
community.docker.docker_image:
name: ghcr.io/company/service:{{ build }}
source: pull
pull:
platform: amd64
- name: Deploy stack
docker_stack:
state: present
name: stack_name
prune: true
compose:
- "/opt/swarm/stack.yml"
If you’re like me and utilize the GitHub Container Registry (ghcr.io
) for Docker images, remember the importance of authentication prior to pulling any images.
Skipping this can lead to pull failures.
- name: Log in to ghcr.io
docker_login:
registry: ghcr.io
username: "{{ ghcr_username }}"
password: "{{ ghcr_token }}"
While this Ansible deployment method for Docker Swarm offers convenience, it does come with certain drawbacks. Notably:
- The method doesn’t inherently wait for the deployment to complete. This means your playbook could move on to subsequent tasks while the deployment is still ongoing.
- There’s no direct feedback mechanism to find out if the deployment was successful or if any errors occurred.
However, it’s worth noting that these limitations aren’t being overlooked. Docker developers are actively addressing this, with discussions and potential solutions being tracked in a dedicated issue: https://github.com/docker/cli/issues/373.
Until there’s an official fix, making your own solution is the way to go.