DevOps.Academy
CoursesCurriculumPricing

    Loading…

    ↑ ↓ move · ↵ open · Ctrl K anywhere

    ◔My learningSign in
    DevOps.Academy

    Free, hands-on DevOps lessons. Made with care in India.

    Learn

    All coursesLinux roadmapCurriculumMy learning

    Academy

    PricingCertificates

    Legal

    PrivacyTermsContact

    devops.rajeev.pro

    DockerLesson 14 of 14
    Your progress · 0%
    On this page
    1. Same image, four homes
    2. Platforms that run it for you
    3. Docker Swarm
    4. Kubernetes
    5. Swarm stacks, secrets and rolling updates
    ↖ Course roadmap
    Lesson 14 · Deploying containers

    Deploying containers: PaaS, Docker Swarm and Kubernetes

    Take the image you built to production: hand it to a platform that runs it for you, spread it across machines with Docker Swarm, or move to Kubernetes, and know which fits your team.

    30 min read · intermediate · hands-on

    By the end of this lesson you'll be able to

    0 of 5 complete

    Same image, four homes

    Everything so far produced one thing: an image in a registry. Where it runs is a separate decision, mostly about how much you want to operate yourself:

    The image doesn't change. Who keeps it running does.© Diagram: DevOps Academy

    The image doesn't change. Who keeps it running does.© Diagram: DevOps Academy

    One server with Compose (lesson 9) is where many products start: docker compose pull && docker compose up -d on a VM, restart policies, backups of the volumes. It's cheap and easy to understand. Its limit: one machine is one failure, and a deploy restarts containers on it.

    Platforms that run it for you

    Container platforms such as Google Cloud Run, AWS App Runner and ECS on Fargate, Azure Container Apps, Fly.io and Render take an image and run it: TLS, load balancing, scaling, restarts and logs are theirs. You give them:

    • the image reference, ideally by digest or SHA tag (lesson 8), and registry credentials;
    • the port your app listens on. Many platforms tell the app with a PORT environment variable, so read it instead of hard-coding 8080;
    • configuration and secrets, set in the platform, not baked in (lesson 11);
    • a health check path such as /health, so bad releases are stopped before they get traffic;
    • CPU, memory and instance limits, which decide the bill.

    The contract is the same everywhere, and it's what the earlier lessons built: log to stdout, keep no state on the container's disk (use a managed database and object storage), start fast, and exit cleanly on SIGTERM, because instances are replaced at any time.

    Docker Swarm

    Swarm mode is built into Docker: it turns several machines into one cluster and runs services, each with a number of replicas. On one machine you can try it in a minute:

    $ docker swarm init --advertise-addr 127.0.0.1
    Swarm initialized: current node (ucnmsfuxg904oob5mjus3gxm3) is now a manager.
    $ docker service create -d --name api --replicas 3 -p 8090:8080 -e APP_VERSION=1.0.0 price-api:multi
    $ docker service ls
    NAME      MODE         REPLICAS   IMAGE             PORTS
    api       replicated   3/3        price-api:multi   *:8090->8080/tcp
    
    docker swarm init --advertise-addr 127.0.0.1
    • dockerbuild and run containers
    • swarmmanage swarm mode
    • initturn this machine into a swarm manager
    docker service create -d --name api --replicas 3 -p 8090:8080 -e APP_VERSION=1.0.0 price-api:multi
    • servicemanage swarm services
    • createcreate one
    • -drun in the background
    • --name apiname the container
    • -p 8090:8080publish a port, host:container
    • -e APP_VERSION=1.0.0set an environment variable inside
    docker service ls
    • lslist them

    A rolling update replaces replicas one at a time:

    $ docker service update --env-add APP_VERSION=1.1.0 --update-parallelism 1 --update-delay 2s api
    $ docker service ps api --format 'table {{.Name}}\t{{.CurrentState}}\t{{.DesiredState}}'
    NAME        CURRENT STATE             DESIRED STATE
    api.1       Running 20 seconds ago    Running
     \_ api.1   Shutdown 21 seconds ago   Shutdown
    api.2       Running 7 seconds ago     Running
     \_ api.2   Shutdown 8 seconds ago    Shutdown
    api.3       Running 14 seconds ago    Running
     \_ api.3   Shutdown 15 seconds ago   Shutdown
    
    docker service update --env-add APP_VERSION=1.1.0 --update-parallelism 1 --update-delay 2s api
    • dockerbuild and run containers
    • servicemanage swarm services
    • updatechange it, with a rolling update
    docker service ps api --format 'table {{.Name}}\t{{.CurrentState}}\t{{.DesiredState}}'
    • pslist the services and their state
    • --format 'table {{.Name}}\t{{.CurrentState}}\t{{.DesiredState}}'print only these fields (Go template)

    And it heals itself. Kill one replica's container and the manager starts a new one, because three are desired:

    $ docker rm -f $(docker ps -q --filter name=api.1)
    $ docker service ps api --filter desired-state=running --format '{{.Name}} {{.CurrentState}}'
    api.1 Running less than a second ago
    api.2 Running 15 seconds ago
    api.3 Running 22 seconds ago
    $ docker service rm api && docker swarm leave --force
    
    docker rm -f $(docker ps -q --filter name=api.1)
    • dockerbuild and run containers
    • rmdelete a container
    • -fstop it first if running
    • $(docker ps -q --filter name=api.1)the container
    docker service ps api --filter desired-state=running --format '{{.Name}} {{.CurrentState}}'
    • servicemanage swarm services
    • pslist the services and their state
    • --filter desired-state=runningshow only matching items
    • --format '{{.Name}} {{.CurrentState}}'print only these fields (Go template)
    docker service rm api && docker swarm leave --force
    • rmdelete one
    • &&run the next command only if this one worked
    • swarmmanage swarm mode
    • leaveleave the swarm

    Other machines join with the docker swarm join command that init prints, and docker stack deploy -c compose.yaml shop runs a Compose file across the cluster, with the deploy: section setting replicas and update order. Swarm is simple and needs little more than Docker skills, but its ecosystem is small; most teams that outgrow one server go to a platform or to Kubernetes.

    Kubernetes

    Kubernetes is the industry's standard orchestrator: the same idea of desired state and self-healing, with far more features and far more to learn. Your Docker knowledge maps straight onto it:

    Docker / ComposeKubernetes
    a containera container in a Pod
    a service with replicas: 3a Deployment
    a service name in DNSa Service
    published port, reverse proxya Service of type LoadBalancer, or an Ingress / Gateway
    environment:, secrets:a ConfigMap, a Secret
    a named volumea PersistentVolumeClaim
    healthcheck:liveness and readiness probes
    mem_limit, cpusresources.requests and limits
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: api
    spec:
      replicas: 3
      selector:
        matchLabels: { app: api }
      template:
        metadata:
          labels: { app: api }
        spec:
          containers:
            - name: api
              image: ghcr.io/acme/price-api:sha-3f9c2e1
              ports: [{ containerPort: 8080 }]
              readinessProbe:
                httpGet: { path: /health, port: 8080 }
              resources:
                limits: { memory: 256Mi, cpu: 500m }
              securityContext:
                runAsNonRoot: true
                allowPrivilegeEscalation: false
                readOnlyRootFilesystem: true
                capabilities: { drop: [ALL] }
    

    Every hardening flag from lesson 11 has a field here. Managed services (EKS, GKE, AKS) run the control plane for you; k3s is a light distribution for small clusters and labs. The Kubernetes course on this site starts where this lesson ends.

    Choosing

    Start with the least you have to operate: a platform, or one server with Compose and good backups. Move to an orchestrator when you have many services, need zero-downtime deploys across machines, or a team to run it. Whatever you pick, deploy immutable images by digest or SHA tag, with health checks, limits and a rollback you've tried.

    Swarm stacks, secrets and rolling updates

    docker stack deploy turns a Compose-shaped file into Swarm services. A Swarm secret is mounted under /run/secrets, not put in an image or command line. Rolling-update settings control parallelism and rollback.

    services:
      api:
        image: price-api:multi
        deploy:
          replicas: 3
          update_config: {parallelism: 1, delay: 5s, order: start-first}
          rollback_config: {parallelism: 1}
    secrets:
      api_token: {external: true}
    
    $ printf 'local-demo-token' | docker secret create api_token -
    $ docker stack deploy -c stack.yml academy
    $ docker service ls
    $ docker service update --rollback academy_api
    $ docker stack rm academy && docker secret rm api_token
    
    printf 'local-demo-token' | docker secret create api_token -
    • |pipe: send output to the next command
    • dockerbuild and run containers
    • -the previous directory
    docker service ls
    • servicemanage swarm services
    • lslist them
    docker service update --rollback academy_api
    • updatechange it, with a rolling update
    docker stack rm academy && docker secret rm api_token
    • &&run the next command only if this one worked
    ⌘
    Mini mission

    Self-healing replicas on your laptop

    Turn your Docker into a one-node swarm, run the price API with three replicas, roll out a new version one replica at a time, kill a replica and watch it come back, then leave the swarm.

    Input: Docker and the price-api:multi image from lesson 7Output: 3/3 replicas, a completed rolling update, a replaced replica, and plain Docker again
    Reveal one safe solution
    $ docker swarm init --advertise-addr 127.0.0.1
    $ docker service create -d --name api --replicas 3 -e APP_VERSION=1.0.0 price-api:multi
    $ docker service ls --format '{{.Name}} {{.Replicas}}'
    api 3/3
    $ docker service update --env-add APP_VERSION=1.1.0 --update-parallelism 1 --update-delay 2s api
    $ docker service ps api                     # each replica: one Running, one Shutdown
    $ docker rm -f $(docker ps -q --filter name=api.1)
    $ docker service ls --format '{{.Name}} {{.Replicas}}'    # back to 3/3 after a few seconds
    api 3/3
    $ docker service rm api && docker swarm leave --force
    $ docker network rm docker_gwbridge         # left behind by swarm mode
    
    docker swarm init --advertise-addr 127.0.0.1
    • dockerbuild and run containers
    • swarmmanage swarm mode
    • initturn this machine into a swarm manager
    docker service create -d --name api --replicas 3 -e APP_VERSION=1.0.0 price-api:multi
    • servicemanage swarm services
    • createcreate one
    • -drun in the background
    • --name apiname the container
    • -e APP_VERSION=1.0.0set an environment variable inside
    docker service ls --format '{{.Name}} {{.Replicas}}'
    • lslist them
    • --format '{{.Name}} {{.Replicas}}'print only these fields (Go template)
    docker service update --env-add APP_VERSION=1.1.0 --update-parallelism 1 --update-delay 2s api
    • updatechange it, with a rolling update
    docker service ps api
    • pslist the services and their state
    docker rm -f $(docker ps -q --filter name=api.1)
    • rmdelete a container
    • -fstop it first if running
    • $(docker ps -q --filter name=api.1)the container
    docker service rm api && docker swarm leave --force
    • rmdelete one
    • &&run the next command only if this one worked
    • leaveleave the swarm
    docker network rm docker_gwbridge
    • networkmanage networks

    You never restarted anything yourself: you declared "three replicas of this image" and Swarm kept it true through an update and a failure. That idea, desired state, is the core of every orchestrator, Kubernetes included.

    Try it yourself

    0 of 6 steps done

    Run each task in your own account or terminal, then tick it off.

    Knowledge check

    Quick check

    Question 1 of 5

    What do all the options in this lesson have in common?

    Go deeper

    Official reading for this lesson

    • DocsDocker Docs: Swarm modeDocker Docs ↗
    • DocsDocker Docs: deploy a stack to a swarmDocker Docs ↗
    • DocsKubernetes: DeploymentsKubernetes ↗
    • DocsGoogle Cloud Run: container runtime contractGoogle Cloud ↗
    • ArticleThe Twelve-Factor App12factor.net ↗

    Or get every quiz answer right and it completes itself.

    ← PreviousDeveloping with Docker: hot reload, debugging, tests and CIUp nextBack to the course roadmap