Comparing Docker compose versions

In this blog, I have captured some of my learnings on Docker compose files and how they differ between versions. Docker compose is a tool used for defining and running multi-container Docker applications. I have used the famous multi-container voting application to illustrate the differences with compose versions.

Following are some questions that I have to tried to answer in this blog:

  • What is the difference between Compose versions 1, 2 and 3?
  • What is the difference between compose, stack and dab formats?
  • What are different ways to run compose files with different compose versions?
  • How does “docker stack deploy” really work?

Compose versions:

Following table captures the main differences between Compose versions:

Feature Compose v1 Compose v2 Compose v3
Docker engine version 1.9.1+ 1.10.0+ 1.13.0+
Compose version Compose up to 1.6.x Compose 1.6.0+ Compose 1.10.0+
Connect containers Bridge network, need links Overlay supported, networks can be used to connect containers Overlay supported, networks can be used to connect containers
Volume No named volume Named volume supported Named volume supported
Swarm capability Older swarm Older swarm Swarm mode
Deploy section No deploy section No deploy section Deploy section with replica present

There could be many reasons why someone would want to use older compose versions. It could either be because they are still using older Docker versions or they already have compose files that are currently in use. I have captured the famous votingapp in all 3 formats to capture the differences:

votingapp in compose v1:

Following is the votingapp in compose v1 format. This establishes container connectivity using links and can be deployed in standalone node or in cluster using old swarm mode.

vote:
    image: docker/example-voting-app-vote:latest
    environment:
      - "constraint:node==swarm-agent-753F9D8C000000"
    ports:
      - "5000:80"
    links:
      - redis

redis:
    image: redis:alpine
    environment:
      - "constraint:node==swarm-agent-753F9D8C000000"
    ports: ["6379"]

worker:
    image: docker/example-voting-app-worker:latest
    environment:
      - "constraint:node==swarm-agent-753F9D8C000000"
    links:
      - redis
      - db

db:
    image: postgres:9.4
    ports: ["5432"]
    environment:
      - "constraint:node==swarm-agent-753F9D8C000000"

result:
    image: tmadams333/example-voting-app-result:latest
    ports:
      - "5001:80"
    environment:
      - "constraint:node==swarm-agent-753F9D8C000000"
    links:
      - db

Following command can be used to deploy:

docker-compose up -d

votingapp in compose v2:

Following is the votingapp in compose v2 format. This establishes container connectivity using networks and can be deployed in standalone node or in cluster using old swarm mode. Containers connected through networks can be deployed in separate nodes and they can talk through overlay network here.

version: "2"

services:
  vote:
    image: docker/example-voting-app-vote:latest
    labels:
     - "com.example.description=Vote"
    ports:
      - "5000:80"
    networks:
      - front-tier
      - back-tier

  redis:
    image: redis:alpine
    ports: ["6379"]
    networks:
      - back-tier

  worker:
    image: docker/example-voting-app-worker:latest
    networks:
      - back-tier

  db:
    image: postgres:9.4
    ports: ["5432"]
    labels:
     - "com.example.description=Postgres Database"
    networks:
      - back-tier

  result:
    image: tmadams333/example-voting-app-result:latest
    ports:
      - "5001:80"
    networks:
      - front-tier
      - back-tier

networks:
  front-tier:
  back-tier:

Following command can be used to deploy:

docker-compose up -d

votingapp in compose v3:

Following is the votingapp in compose v3 format. This establishes container connectivity using networks and can be deployed in standalone node or in new swarm mode. This compose format has the deploy section that controls deployment parameters like number of replicas, constraints etc.

version: "3"
services:

  redis:
    image: redis:alpine
    ports:
      - "6379"
    networks:
      - frontend
    deploy:
      replicas: 2
      update_config:
        parallelism: 2
        delay: 10s
      restart_policy:
        condition: on-failure
  db:
    image: postgres:9.4
    volumes:
      - db-data:/var/lib/postgresql/data
    networks:
      - backend
    deploy:
      placement:
        constraints: [node.role == manager]
  vote:
    image: dockersamples/examplevotingapp_vote:before
    ports:
      - 5000:80
    networks:
      - frontend
    depends_on:
      - redis
    deploy:
      replicas: 2
      update_config:
        parallelism: 2
      restart_policy:
        condition: on-failure
  result:
    image: dockersamples/examplevotingapp_result:before
    ports:
      - 5001:80
    networks:
      - backend
    depends_on:
      - db
    deploy:
      replicas: 1
      update_config:
        parallelism: 2
        delay: 10s
      restart_policy:
        condition: on-failure

  worker:
    image: dockersamples/examplevotingapp_worker
    networks:
      - frontend
      - backend
    deploy:
      mode: replicated
      replicas: 1
      labels: [APP=VOTING]
      restart_policy:
        condition: on-failure
        delay: 10s
        max_attempts: 3
        window: 120s
      placement:
        constraints: [node.role == manager]

networks:
  frontend:
  backend:

volumes:
  db-data:

There are 2 ways to deploy an application in compose v3 format. The first is the traditional option using docker-compose.

docker-compose up -d

The above option ignores the parameters under deploy section.

The second preferred option is to use “docker stack” approach as shown below. With this, the Docker services gets directly deployed in the Swarm mode cluster.

docker stack deploy --compose-file  vote

In “docker stack deploy”, compose file parsing is done by Docker engine itself compared to docker-compose binary handling compose file parsing. There are few options still missing in “docker stack deploy”. 1 of them is environment variables which has been addressed recently and should be available in 17.04 Docker version. Another is related to “extends” feature and is being discussed here. The general goal is get Docker engine have all features of docker-compose so that “docker stack deploy” would become the universal way to deploy compose files.

Difference between compose, stack and dab file formats:

Stack file is same as compose file with additional deploy section. Stack file is part of Compose v3 format. If we are using new Swarm mode, it is better to move to stack file format which is the same as compose v3.

Distributed application bundle(Dab) was introduced in Docker 1.12 as an experimental feature. dab file specifies container image with digest rather than defining container image with tags. dab file is auto-generated from docker-compose file. Many options of compose is not supported in dab. “docker stack” introduced in Docker 1.13 has the capabilities of compose and dab combined. My understanding is “docker stack” will make dab format obsolete. I checked with few folks in Docker team and this seems to be the case though it is not fully confirmed.

To generate dab from compose file, we can use the following command:

docker-compose bundle -o 

To deploy the bundle, we can use the docker stack command:

docker stack deploy --bundle-file  

Following is the votingapp in dab format:

{
  "Services": {
    "db": {
      "Image": "postgres@sha256:c681c72ff62b637b9ad3806a946f14450f74ee0888ca70ec1472a4e0552054c2", 
      "Networks": [
        "backend"
      ]
    }, 
    "redis": {
      "Image": "redis@sha256:95f0c9434f37db0a4f9563379184ff4895685d2381e2d81bd10dfcbcadfc095f", 
      "Networks": [
        "frontend"
      ], 
      "Ports": [
        {
          "Port": 6379, 
          "Protocol": "tcp"
        }
      ]
    }, 
    "result": {
      "Image": "dockersamples/examplevotingapp_result@sha256:83b568996e930c292a6ae5187fda84dd6568a19d97cdb933720be15c757b7463", 
      "Networks": [
        "backend"
      ], 
      "Ports": [
        {
          "Port": 80, 
          "Protocol": "tcp"
        }
      ]
    }, 
    "visualizer": {
      "Image": "dockersamples/visualizer@sha256:f924ad66c8e94b10baeaf7bdb9cd491ef4e982a1d048a56a17e02bf5945401e5", 
      "Networks": [
        "default"
      ], 
      "Ports": [
        {
          "Port": 8080, 
          "Protocol": "tcp"
        }
      ]
    }, 
    "vote": {
      "Image": "dockersamples/examplevotingapp_vote@sha256:8e64b18b2c87de902f2b72321c89b4af4e2b942d76d0b772532ff27ec4c6ebf6", 
      "Networks": [
        "frontend"
      ], 
      "Ports": [
        {
          "Port": 80, 
          "Protocol": "tcp"
        }
      ]
    }, 
    "worker": {
      "Image": "dockersamples/examplevotingapp_worker@sha256:3e4dd0f59c15f432280a2c0679c4fc5a2ee5a797023c8ef0d3baf7b1385e9fed", 
      "Networks": [
        "frontend", 
        "backend"
      ]
    }
  }, 
  "Version": "0.1"
}

How does “docker stack deploy” really work?

I have prepared the flowchart below based on referring the notes from this issue. The flowchart below shows how the image specified in the compose file resolves to what gets deployed finally when “docker stack deploy” is used.

compose2

“docker stack deploy” is idempotent. If the stack is already deployed, “docker stack deploy” will restart only those services which has the digest or tag that is updated. In the above flowchart, the restart applies to the 2 cases where the latest image is pulled from registry.

References:

Kubernetes CRI and Minikube

Kubernetes CRI(Container runtime interface) is introduced in experimental mode in Kubernetes 1.15 release. Kubernetes CRI introduces a common Container runtime layer that allows for Kubernetes orchestrator to work with multiple Container runtimes like Docker, Rkt, Runc, Hypernetes etc. CRI makes it easy to plug in a new Container runtime to Kubernetes. Minikube project simplifies Kubernetes installation for development and testing purposes. Minikube project allows Kubernetes master and worker components to run in a single VM which facilitates developers and users of Kubernetes to easily try out Kubernetes. In this blog, I will cover basics of Minikube usage, overview of CRI and steps to try out CRI with Minikube.

Minikube

Kubernetes software is composed of multiple components and beginners normally get overwhelmed with the installation steps. It is also easier to have a lightweight Kubernetes environment for development and testing purposes. Minikube has all Kubernetes components in a single VM that runs in the local laptop. Both master and worker functionality is combined in the single VM.

Following are some major features present in Minikube:

Continue reading Kubernetes CRI and Minikube

Docker 1.13 Experimental features

Docker 1.13 version got released last week. Some of the significant new features include Compose support to deploy Swarm mode services, supporting backward compatibility between Docker client and server versions, Docker system commands to manage Docker host and restructured Docker CLI. In addition to these major features, Docker introduced a bunch of experimental features in 1.13 release. In every release, Docker introduces few new Experimental features. These are features that are not yet ready for production purposes. Docker puts out these features in experimental mode so that it can collect feedback from its users and make modifications when the feature gets officially released in the next set of releases. In this blog, I will cover the experimental features introduced in Docker 1.13.

Following are the regular features introduced in Docker 1.13:

  • Deploying Docker stack on Swarm cluster with Docker compose.
  • Docker cli with Docker daemon backward compatibility. This allows newer Docker CLI to talk to older Docker daemons.
  • Docker cli new options like “docker container”, “docker image” to collect related commands in docker sub-keyword.
  • Docker system details using “docker system” – This helps in maintaining Docker host for cleanup and to get Container usage details
  • Docker secret management
  • docker build with compress option for slow connections

Following are the 5 features introduced in experimental mode in Docker 1.13:

  • Experimental daemon flag to enable experimental features instead of having separate experimental build.
  • Docker service logs command to view logs for a Docker service. This is needed in Swarm mode.
  • Option to squash image layers to the base image after successful builds.
  • Checkpoint and restore support for Containers.
  • Metrics (Prometheus) output for basic container, image, and daemon operations.

Experimental Daemon flag

Docker released experimental features prior to 1.13 release as well. In earlier release, users needed to download a new Docker image to try out experimental features. To avoid this unnecessary overhead of having different images, Docker introduced a experimental flag or option to Docker daemon so that users can start the Docker daemon with or without experimental features. With Docker 1.13 release, Docker experimental flag is in experimental mode.

By default, experimental flag is turned off. To see the experimental flag, check Docker version.

Continue reading Docker 1.13 Experimental features

Hybrid cloud recent solutions from Microsoft and VMWare – 2 different ends of the hybrid cloud spectrum

Public clouds have grown tremendously over the last few years and there are very few companies who do not use public cloud at this point. Even traditional enterprises with in-house data centers have some presence in the public cloud. I was looking at Amazon’s re:Invent conference details and I was amazed by the number of new services and enhancements that were announced this year.  It is very difficult for private clouds to keep up in pace with the new features of public cloud. There is no doubt that public clouds will overtake private clouds in the long term. Private clouds still have a wide deployment and there will be enough use cases for quite some time to deploy private cloud. The use cases includes regulated industries, compute needed in remote locations not having access to public cloud and some specialized requirements that public clouds cannot meet. For some enterprises, private cloud would make more sense from a costing perspective. Having hybrid cloud option is a safe bet for most companies as it provides the best of both worlds. I saw 2 recent announcements in hybrid cloud that captured my attention. One is Azure stack that allows running Azure stack in private cloud. Another is VMWare cloud on AWS that allows running entire VMware stack in AWS public cloud. I see these two services as 2 ends of the hybrid cloud spectrum. In 1 case, public cloud infrastructure software is made to run on private cloud(Azure stack) and in another case, private cloud infrastructure software is made to run on public cloud(Vmware cloud on AWS). In this blog, I have tried to capture more details on these 2 services.

Hybrid cloud

There are predominantly 2 options currently to run Private cloud. 1 option is to use vendor based cloud management software along with hardware from same vendor.

Continue reading Hybrid cloud recent solutions from Microsoft and VMWare – 2 different ends of the hybrid cloud spectrum

Docker in Docker and play-with-docker

For folks who want to get started with Docker, there is the initial hurdle of installing Docker. Even though Docker has made it extremely simple to install Docker on different OS like Linux, Windows and Mac, the installation step prevents folks from getting started with Docker. With Play with Docker, that problem also goes away. Play with Docker provides a web based interface to create multiple Docker hosts and be able to run Containers. This project is started by Docker captain Marcos Nils and is an open source project. Users can run regular containers or build Swarm cluster between the Docker hosts and create container services on the Swarm cluster. The application can also be installed in the local machine. This project got me interested in trying to understand the internals of the Docker host used within the application. I understood that Docker hosts are implemented as Docker in Docker(Dind) containers. In this blog, I have tried to cover some details on Dind and Play with Docker.

Docker in Docker(Dind)

Docker in Docker(Dind) allows Docker engine to run as a Container inside Docker. This link is the official repository for Dind. When there is a new Docker version released, corresponding Dind version also gets released. This link from Jerome is an excellent reference on Docker in Docker that explains issues with Dind, cases where Dind can be used and cases where Dind should not be used.

Following are the two primary scenarios where Dind can be needed:

Continue reading Docker in Docker and play-with-docker

Vault – Use cases

This blog is a continuation of my previous blog on Vault. In the first blog, I have covered overview of Vault. In this blog, I will cover some Vault use cases that I tried out.

Pre-requisites:

Install and start Vault

I have used Vault 0.6 version for the examples here. Vault can be used either in development or production mode. In development mode, Vault is unsealed by default and secrets are stored only in memory. Vault in production mode needs manual unsealing and supports backends like Consul, S3.

Start Vault server:

Following command starts Vault server in development mode. We need to note down the root key that will be used later.

Continue reading Vault – Use cases