{"id":2319,"date":"2017-01-06T07:06:55","date_gmt":"2017-01-06T07:06:54","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=2319"},"modified":"2023-11-17T08:43:26","modified_gmt":"2023-11-17T16:43:26","slug":"docker-services-stack-distributed-application-bundle","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/docker-services-stack-distributed-application-bundle\/","title":{"rendered":"Docker Services, Stack and Distributed Application Bundle"},"content":{"rendered":"<p><a href=\"\/wp-content\/original-assets\/july2015\/docker-services-stack-and-distributed-application-bundle\/docker-1.12.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-14057 size-full\" src=\"\/wp-content\/original-assets\/july2015\/docker-services-stack-and-distributed-application-bundle\/docker-1.12.jpg\" alt=\"docker-1.12\" width=\"280\" height=\"300\" \/><\/a><\/p>\n<p><a href=\"https:\/\/github.com\/docker\/docker\/releases\/tag\/v1.12.0-rc1\">First Release Candidate of Docker 1.12<\/a> was announced over <a href=\"https:\/\/blog.docker.com\/2016\/06\/docker-1-12-built-in-orchestration\/\">two weeks ago<\/a>. Several new features are<br \/>\nplanned for this release.<\/p>\n<p>This blog will show\u00a0how to create a <a href=\"https:\/\/www.couchbase.com\/blog\/distributed-applications\/\">Distributed Application<\/a> Bundle from Docker Compose and deploy it as Docker Stack in <a href=\"https:\/\/www.couchbase.com\/blog\/deploy-docker-compose-services-swarm\/\">Docker Swarm<\/a> Mode. Many thanks to <a href=\"https:\/\/twitter.com\/friism\">@friism<\/a>\u00a0for helping me understand these concepts.<\/p>\n<p>Let&#8217;s look at the features first:<\/p>\n<ul>\n<li><strong>Built-in orchestration<\/strong>: A typical application is defined using a Docker Compose file. This definition consists of multiple containers and deployed on multiple hosts. This avoids Single Point of Failure (SPOF) and keeps your application<br \/>\nresilient. Multiple orchestration frameworks such as Docker Swarm, Kubernetes and Mesos allow you to orchestrate these applications. However it is such an important characteristic of the application, Docker Engine now has built-in orchestration.<br \/>\nMore details on this topic in a later blog.<\/li>\n<li><strong>Service<\/strong>: A replicated, distributed and load balanced service can be easily created using <code>docker service create<\/code> command. A &#8220;desired state&#8221; of the application, such as run 3 containers of Couchbase, is provided and the<br \/>\nself-healing Docker engine ensures that that many containers are running in the cluster. If a container goes down, another container is started. If a node goes down, containers on that node are started on a different node. More on this in a later<br \/>\nblog.<\/li>\n<li><strong>Zero-configuration Security<\/strong>: Docker 1.12 comes with mutually authenticated TLS, providing authentication, authorization and encryption to the communications of every node participating in the swarm, out of the box. More on this in<br \/>\na later blog.<\/li>\n<li><strong>Docker Stack and Distributed Application Bundle<\/strong>: Distributed Application Bundle, or DAB, is a multi-services distributable image format. Read further for more details.<\/li>\n<\/ul>\n<p>So far, you can take a <code>Dockerfile<\/code>\u00a0and create an image from it using the <code>docker build<\/code> command.\u00a0A container can be started using the\u00a0<code>docker run<\/code> command. Multiple containers can be easily started by giving<br \/>\nthat command multiple times.\u00a0Or you can also use Docker\u00a0Compose file and scale up\u00a0your containers using the <code>docker-compose scale<\/code> command.<br \/>\n<a href=\"\/wp-content\/original-assets\/july2015\/docker-services-stack-and-distributed-application-bundle\/docker-lifecycle-1024x329.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-14051\" src=\"\/wp-content\/original-assets\/july2015\/docker-services-stack-and-distributed-application-bundle\/docker-lifecycle-1024x329.png\" alt=\"docker-lifecycle\" width=\"604\" height=\"194\" \/><\/a><\/p>\n<p>Image is a portable format for a single container. <a href=\"https:\/\/docker.com\/dab\">Distributed Application Bundle<\/a>, or DAB, is a new concept introduced in Docker 1.12, is a portable format for multiple containers. Each bundle can be then deployed as<br \/>\na <em>Stack<\/em>\u00a0at runtime.<\/p>\n<p><a href=\"\/wp-content\/original-assets\/july2015\/docker-services-stack-and-distributed-application-bundle\/docker-stack-lifecycle-1024x344.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-14052\" src=\"\/wp-content\/original-assets\/july2015\/docker-services-stack-and-distributed-application-bundle\/docker-stack-lifecycle-1024x344.png\" alt=\"docker-stack-lifecycle\" width=\"604\" height=\"203\" \/><\/a><\/p>\n<p>Learn more about DAB at <a href=\"https:\/\/docker.com\/dab\">docker.com\/dab<\/a>. For simplicity, here is an analogy that can be drawn:<\/p>\n<p><strong>Dockerfile -&gt; Image -&gt; Container<\/strong><\/p>\n<p><strong>Docker Compose -&gt; Distributed Application Bundle -&gt; Docker Stack<\/strong><\/p>\n<p>Let&#8217;s\u00a0use a Docker Compose file, create a DAB\u00a0from it, and deploy it as a Docker Stack.<\/p>\n<p><span style=\"color: #333333;line-height: 20.8px;text-align: left\">Its important to note that this is an experimental feature in 1.12-RC2.<\/span><\/p>\n<h2>Create a\u00a0Distributed\u00a0Application Bundle from Docker Compose<\/h2>\n<p>Docker Compose CLI adds a new <code>bundle<\/code> command. More details can be found:<\/p>\n<pre class=\"lang:default decode:true\">docker-compose bundle --help\r\nGenerate a Docker bundle from the Compose file.\r\n\r\nLocal images will be pushed to a Docker registry, and remote images\r\nwill be pulled to fetch an image digest.\r\n\r\nUsage: bundle [options]\r\n\r\nOptions:\r\n    -o, --output PATH          Path to write the bundle file to.\r\n                               Defaults to \".dsb\".<\/pre>\n<p>Now, let&#8217;s take a Docker Compose definition and create a DAB from it.\u00a0Here is our\u00a0Docker\u00a0Compose\u00a0definition:<\/p>\n<pre class=\"lang:default decode:true\">version: \"2\"\r\nservices:\r\n  db:\r\n    container_name: \"db\"\r\n    image: arungupta\/oreilly-couchbase:latest\r\n    ports:\r\n      - 8091:8091\r\n      - 8092:8092 \r\n      - 8093:8093 \r\n      - 11210:11210\r\n  web:\r\n    image: arungupta\/oreilly-wildfly:latest\r\n    depends_on:\r\n      - db\r\n    environment:\r\n      - COUCHBASE_URI=db\r\n    ports:\r\n      - 8080:8080<\/pre>\n<p>This Compose file starts a WildFly and a Couchbase server. A Java EE application is pre-deployed in the WildFly server that connects to the Couchbase server and allows to perform CRUD operations using the REST API. The source for this file is at:<br \/>\n<a href=\"https:\/\/github.com\/arun-gupta\/oreilly-docker-book\/blob\/master\/hello-javaee\/docker-compose.yml\">github.com\/arun-gupta\/oreilly-docker-book\/blob\/master\/hello-javaee\/docker-compose.yml<\/a>. Generate an application bundle with it:<\/p>\n<pre class=\"lang:default decode:true\">docker-compose bundle\r\nWARNING: Unsupported key 'depends_on' in services.web - ignoring\r\nWARNING: Unsupported key 'container_name' in services.db - ignoring\r\nWrote bundle to hellojavaee.dsb<\/pre>\n<p><code>depends_on<\/code> only creates dependency between two services and makes them start in a specific order. This only ensures that the Docker container\u00a0is started but the application within the container may take longer to start. So this attribute\u00a0only<br \/>\npartially solves the problem.\u00a0<code>container_name<\/code> gives a specific\u00a0name to the container. Relying upon a specific container name is tight coupling and does not allow to scale the container. \u00a0So both the warnings can be ignored,<br \/>\nfor now. This command generates\u00a0a file\u00a0using the Compose project name, which is the directory name. So in our case, <code>hellojavaee.dsb<\/code> file is generated. This file extension has been renamed to <code>.dab<\/code> in RC3. The generated<br \/>\napplication bundle looks like:<\/p>\n<pre class=\"lang:default decode:true\">{\r\n  \"services\": {\r\n    \"db\": {\r\n      \"Image\": \"arungupta\/oreilly-couchbase@sha256:f150fcb9fca5392075c96f1baffc7f893858ba763f3c05cf0908ef2613cbf34c\", \r\n      \"Networks\": [\r\n        \"default\"\r\n      ], \r\n      \"Ports\": [\r\n        {\r\n          \"Port\": 8091, \r\n          \"Protocol\": \"tcp\"\r\n        }, \r\n        {\r\n          \"Port\": 8092, \r\n          \"Protocol\": \"tcp\"\r\n        }, \r\n        {\r\n          \"Port\": 8093, \r\n          \"Protocol\": \"tcp\"\r\n        }, \r\n        {\r\n          \"Port\": 11210, \r\n          \"Protocol\": \"tcp\"\r\n        }\r\n      ]\r\n    }, \r\n    \"web\": {\r\n      \"Env\": [\r\n        \"COUCHBASE_URI=db\"\r\n      ], \r\n      \"Image\": \"arungupta\/oreilly-wildfly@sha256:d567ade7bb82ba8f15a85df0c6d692d85c15ec5a78d8826dfba92756babcb914\", \r\n      \"Networks\": [\r\n        \"default\"\r\n      ], \r\n      \"Ports\": [\r\n        {\r\n          \"Port\": 8080, \r\n          \"Protocol\": \"tcp\"\r\n        }\r\n      ]\r\n    }\r\n  }, \r\n  \"version\": \"0.1\"\r\n}<\/pre>\n<p>This\u00a0file provides complete description of the\u00a0services included in the application.\u00a0I&#8217;m not entirely sure if Distributed Application Bundle is the most appropriate name, discuss this in\u00a0<a href=\"https:\/\/github.com\/docker\/docker\/issues\/24250\">#24250<\/a>.\u00a0It<br \/>\nwould be great if\u00a0other container formats, such as Rkt, or even VMs can be supported here. But for now, Docker\u00a0is the only\u00a0supported format.<\/p>\n<h2>Initialize Swarm Mode in Docker<\/h2>\n<p>As mentioned above, &#8220;desired state&#8221; is now maintained by Docker\u00a0Swarm. And this is now baked into Docker Engine already. Docker Swarm concepts have evolved as well and can be read at <a href=\"https:\/\/docs.docker.com\/engine\/swarm\/key-concepts\/\">Swarm mode key concepts<\/a>.\u00a0A<br \/>\nmore detailed blog on this will be coming later. But for this blog,\u00a0a\u00a0new command\u00a0<code>docker swarm<\/code> is now added:<\/p>\n<pre class=\"lang:default decode:true\">docker swarm --help\r\n\r\nUsage: docker swarm COMMAND\r\n\r\nManage Docker Swarm\r\n\r\nOptions:\r\n      --help   Print usage\r\n\r\nCommands:\r\n  init        Initialize a Swarm\r\n  join        Join a Swarm as a node and\/or manager\r\n  update      Update the Swarm\r\n  leave       Leave a Swarm\r\n  inspect     Inspect the Swarm\r\n\r\nRun 'docker swarm COMMAND --help' for more information on a command.<\/pre>\n<p>Initialize a Swarm node (as a manager) in the Docker Engine:<\/p>\n<pre class=\"lang:default decode:true\">docker swarm init\r\nSwarm initialized: current node (ek9p1k8r8ox7iiua5c247skci) is now a manager.<\/pre>\n<p>More details about this node can be found using <code>docker node inspect<\/code> self command.<\/p>\n<p>The detailed output is verbose but the relevant section is:<\/p>\n<pre>\"Spec\": {\r\n            \"Role\": \"manager\",\r\n            \"Membership\": \"accepted\",\r\n            \"Availability\": \"active\"\r\n        },\r\n<\/pre>\n<p>The output shows that the node is a manager. For a single-node cluster, this node will also act as a worker.<\/p>\n<p>More details about the cluster can be obtained using the <code>docker swarm inspect<\/code> command.<\/p>\n<pre class=\"lang:default decode:true\">docker swarm inspect\r\n[\r\n    {\r\n        \"ID\": \"1rcvu7m9mv2c8hiaijr7an9zk\",\r\n        \"Version\": {\r\n            \"Index\": 1895\r\n        },\r\n        \"CreatedAt\": \"2016-07-01T23:52:38.074748177Z\",\r\n        \"UpdatedAt\": \"2016-07-02T04:54:32.79093117Z\",\r\n        \"Spec\": {\r\n            \"Name\": \"default\",\r\n            \"AcceptancePolicy\": {\r\n                \"Policies\": [\r\n                    {\r\n                        \"Role\": \"worker\",\r\n                        \"Autoaccept\": true\r\n                    },\r\n                    {\r\n                        \"Role\": \"manager\",\r\n                        \"Autoaccept\": false\r\n                    }\r\n                ]\r\n            },\r\n            \"Orchestration\": {\r\n                \"TaskHistoryRetentionLimit\": 10\r\n            },\r\n            \"Raft\": {\r\n                \"SnapshotInterval\": 10000,\r\n                \"LogEntriesForSlowFollowers\": 500,\r\n                \"HeartbeatTick\": 1,\r\n                \"ElectionTick\": 3\r\n            },\r\n            \"Dispatcher\": {\r\n                \"HeartbeatPeriod\": 5000000000\r\n            },\r\n            \"CAConfig\": {\r\n                \"NodeCertExpiry\": 7776000000000000\r\n            }\r\n        }\r\n    }\r\n]<\/pre>\n<p><code>AcceptancePolicy<\/code> shows that other <code>worker<\/code> nodes can join this cluster, but a manager requires explicit approval.<\/p>\n<h2>Deploy\u00a0a Docker Stack<\/h2>\n<p>Create a stack using <code>docker deploy<\/code> command:<\/p>\n<pre class=\"lang:default decode:true\">docker deploy -f hellojavaee.dsb hellojavaee\r\nLoading bundle from hellojavaee.dsb\r\nCreating network hellojavaee_default\r\nCreating service hellojavaee_db\r\nCreating service hellojavaee_web<\/pre>\n<p>The command usage can certainly be simplified as discussed in\u00a0<a href=\"https:\/\/github.com\/docker\/docker\/issues\/24249\">#24249<\/a>. See the list of services:<\/p>\n<pre class=\"lang:default decode:true\">docker service ls\r\nID            NAME             REPLICAS  IMAGE                                                                                                COMMAND\r\n2g8kmrimztes  hellojavaee_web  1\/1       arungupta\/oreilly-wildfly@sha256:d567ade7bb82ba8f15a85df0c6d692d85c15ec5a78d8826dfba92756babcb914    \r\n46xhlb15cc60  hellojavaee_db   1\/1       arungupta\/oreilly-couchbase@sha256:f150fcb9fca5392075c96f1baffc7f893858ba763f3c05cf0908ef2613cbf34c<\/pre>\n<p>The output shows that two\u00a0services, WildFly and Couchbase, are running. <a href=\"https:\/\/docs.docker.com\/engine\/swarm\/key-concepts\/#\/Services-and-tasks\">Services<\/a> is also a new concept introduced in Docker 1.12. There\u00a0is what gives you\u00a0the<br \/>\n&#8220;desired state&#8221; and Docker Engine works to give you that. <code>docker ps<\/code> shows the list of containers running:<\/p>\n<pre class=\"lang:default decode:true\">CONTAINER ID        IMAGE                                                                                                 COMMAND                  CREATED             STATUS              PORTS                                                        NAMES\r\n622756277f40        arungupta\/oreilly-couchbase@sha256:f150fcb9fca5392075c96f1baffc7f893858ba763f3c05cf0908ef2613cbf34c   \"\/entrypoint.sh \/opt\/\"   3 seconds ago       Up 1 seconds        8091-8093\/tcp, 11207\/tcp, 11210-11211\/tcp, 18091-18092\/tcp   hellojavaee_db.1.19enwdt6i5m853m5675tx3z29\r\nabf8703ed713        arungupta\/oreilly-wildfly@sha256:d567ade7bb82ba8f15a85df0c6d692d85c15ec5a78d8826dfba92756babcb914     \"\/opt\/jboss\/wildfly\/b\"   3 seconds ago       Up 1 seconds        8080\/tcp                                                     hellojavaee_web.1.70piloz6j4zt06co8htzisgyl<\/pre>\n<p>WildFly container starts up before the Couchbase container is up and running. This means the\u00a0Java EE application tries to connect to the Couchbase server and fails.\u00a0So the application never boots successfully.<\/p>\n<h2>Self-healing Docker Service<\/h2>\n<p>Docker Service maintains the &#8220;desired state&#8221; of an application. In our case, the desired state is to ensure that\u00a0one, and only one, container for the service is running.\u00a0If we\u00a0remove the container, not the service, then the service will<br \/>\nautomatically start the container again. Remove the container as:<\/p>\n<pre class=\"lang:default decode:true\">docker rm -f abf8703ed713<\/pre>\n<p>Note, you&#8217;ve to give <code>-f<\/code> because the container is already running. Docker 1.12 self-healing\u00a0mechanisms kick in and automatically restart the container. Now if you list the containers again:<\/p>\n<pre class=\"lang:default decode:true\">CONTAINER ID        IMAGE                                                                                                 COMMAND                  CREATED             STATUS                  PORTS                                                        NAMES\r\ndb483ac27e41        arungupta\/oreilly-wildfly@sha256:d567ade7bb82ba8f15a85df0c6d692d85c15ec5a78d8826dfba92756babcb914     \"\/opt\/jboss\/wildfly\/b\"   1 seconds ago       Up Less than a second   8080\/tcp                                                     hellojavaee_web.1.ddvwdmojjysf46d4n3x4g8uv4\r\n622756277f40        arungupta\/oreilly-couchbase@sha256:f150fcb9fca5392075c96f1baffc7f893858ba763f3c05cf0908ef2613cbf34c   \"\/entrypoint.sh \/opt\/\"   26 seconds ago      Up 25 seconds           8091-8093\/tcp, 11207\/tcp, 11210-11211\/tcp, 18091-18092\/tcp   hellojavaee_db.1.19enwdt6i5m853m5675tx3z29<\/pre>\n<p>This shows that a new container has been started. Inspect the WildFly service:<\/p>\n<pre class=\"lang:default decode:true\">docker service inspect hellojavaee_web\r\n[\r\n    {\r\n        \"ID\": \"54otfi6dc9bis7z6gc6ubynwc\",\r\n        \"Version\": {\r\n            \"Index\": 328\r\n        },\r\n        \"CreatedAt\": \"2016-07-02T01:36:35.735767569Z\",\r\n        \"UpdatedAt\": \"2016-07-02T01:36:35.739240775Z\",\r\n        \"Spec\": {\r\n            \"Name\": \"hellojavaee_web\",\r\n            \"Labels\": {\r\n                \"com.docker.stack.namespace\": \"hellojavaee\"\r\n            },\r\n            \"TaskTemplate\": {\r\n                \"ContainerSpec\": {\r\n                    \"Image\": \"arungupta\/oreilly-wildfly@sha256:d567ade7bb82ba8f15a85df0c6d692d85c15ec5a78d8826dfba92756babcb914\",\r\n                    \"Env\": [\r\n                        \"COUCHBASE_URI=db\"\r\n                    ]\r\n                }\r\n            },\r\n            \"Mode\": {\r\n                \"Replicated\": {\r\n                    \"Replicas\": 1\r\n                }\r\n            },\r\n            \"Networks\": [\r\n                {\r\n                    \"Target\": \"epw57lz7txtfchmbf6u0cimis\",\r\n                    \"Aliases\": [\r\n                        \"web\"\r\n                    ]\r\n                }\r\n            ],\r\n            \"EndpointSpec\": {\r\n                \"Mode\": \"vip\",\r\n                \"Ports\": [\r\n                    {\r\n                        \"Protocol\": \"tcp\",\r\n                        \"TargetPort\": 8080\r\n                    }\r\n                ]\r\n            }\r\n        },\r\n        \"Endpoint\": {\r\n            \"Spec\": {},\r\n            \"Ports\": [\r\n                {\r\n                    \"Protocol\": \"tcp\",\r\n                    \"TargetPort\": 8080,\r\n                    \"PublishedPort\": 30004\r\n                }\r\n            ],\r\n            \"VirtualIPs\": [\r\n                {\r\n                    \"NetworkID\": \"9lpz688ir3pzexubkcb828ikg\",\r\n                    \"Addr\": \"10.255.0.5\/16\"\r\n                },\r\n                {\r\n                    \"NetworkID\": \"epw57lz7txtfchmbf6u0cimis\",\r\n                    \"Addr\": \"10.0.0.4\/24\"\r\n                }\r\n            ]\r\n        }\r\n    }\r\n]<\/pre>\n<p>Swarm assigns a\u00a0random port to the service, or this can be manually updated using <code>docker service update<\/code> command. In our case, port <code>8080<\/code> of the container is mapped to <code>30004<\/code> port on the host.<\/p>\n<h2>Verify the\u00a0Application<\/h2>\n<p>Check that the application is successfully deployed:<\/p>\n<pre class=\"lang:default decode:true\">curl https:\/\/localhost:30004\/books\/resources\/book\r\n[{\"books\":0}]<\/pre>\n<p>Add a new book to the application:<\/p>\n<pre class=\"lang:default decode:true\">curl -v \r\n&gt; -H \"Content-Type: application\/json\" \r\n&gt; -X POST -d '{\r\n&gt;   \"isbn\": \"978-1-4919-1889-0\",\r\n&gt;   \"name\": \"Minecraft Modding with Forge\",\r\n&gt;   \"cost\": 29.99\r\n&gt; }' \r\n&gt; https:\/\/localhost:30004\/books\/resources\/book\r\n*   Trying ::1...\r\n* Connected to localhost (::1) port 30004 (#0)\r\n&gt; POST \/books\/resources\/book HTTP\/1.1\r\n&gt; Host: localhost:30004\r\n&gt; User-Agent: curl\/7.43.0\r\n&gt; Accept: *\/*\r\n&gt; Content-Type: application\/json\r\n&gt; Content-Length: 92\r\n&gt; \r\n* upload completely sent off: 92 out of 92 bytes\r\n&lt; HTTP\/1.1 200 OK\r\n&lt; Connection: keep-alive\r\n&lt; X-Powered-By: Undertow\/1\r\n&lt; Server: WildFly\/10\r\n&lt; Content-Type: application\/octet-stream\r\n&lt; Content-Length: 88\r\n&lt; Date: Sat, 02 Jul 2016 01:39:49 GMT\r\n&lt; \r\n* Connection #0 to host localhost left intact\r\n{\"name\":\"Minecraft Mhttps:\/\/localhost:30004\/books\/resources\/book-1-4919-1889-0\"}<\/pre>\n<p>Verify the books again:<\/p>\n<pre class=\"lang:default decode:true\">curl https:\/\/localhost:30004\/books\/resources\/book\r\n[{\"books\":{\"name\":\"Minecraft Modding with Forge\",\"cost\":29.99,\"id\":\"1\",\"isbn\":\"978-1-4919-1889-0\"}}, {\"books\":1}]<\/pre>\n<p>Learn more about this Java EE application at\u00a0<a href=\"https:\/\/github.com\/arun-gupta\/oreilly-docker-book\/tree\/master\/hello-javaee\">github.com\/arun-gupta\/oreilly-docker-book\/tree\/master\/hello-javaee<\/a>.<\/p>\n<p>This blog showed how to create a Distributed Application Bundle from Docker Compose and deploy it as Docker Stack in Docker Swarm Mode.<\/p>\n<h2>Docker Service and Stack References<\/h2>\n<ul>\n<li><a href=\"https:\/\/docs.docker.com\/engine\/reference\/commandline\/service_create\/\">Docker Service Create<\/a><\/li>\n<li>FREE book from O&#8217;Reilly:\u00a0<a href=\"https:\/\/shop.oreilly.com\/product\/0636920050872.do\">Docker for Java Developers<\/a><\/li>\n<li><a href=\"https:\/\/couchbase.com\/containers\/\">Couchbase on Containers<\/a><\/li>\n<li><a href=\"https:\/\/developer.couchbase.com\/server\">Couchbase\u00a0Developer Portal<\/a><\/li>\n<li>Ask questions on <a href=\"https:\/\/twitter.com\/couchbasedev\">@couchbasedev<\/a> or <a href=\"https:\/\/stackoverflow.com\/questions\/tagged\/couchbase\">Stackoverflow<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>First Release Candidate of Docker 1.12 was announced over two weeks ago. Several new features are planned for this release. This blog will show\u00a0how to create a Distributed Application Bundle from Docker Compose and deploy it as Docker Stack in [&hellip;]<\/p>\n","protected":false},"author":58,"featured_media":13873,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1],"tags":[],"ppma_author":[8933],"class_list":["post-2319","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.8 (Yoast SEO v25.8) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Docker Services, Stack &amp; Distributed Application Bundle<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.couchbase.com\/blog\/docker-services-stack-distributed-application-bundle\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Docker Services, Stack and Distributed Application Bundle\" \/>\n<meta property=\"og:description\" content=\"First Release Candidate of Docker 1.12 was announced over two weeks ago. Several new features are planned for this release. This blog will show\u00a0how to create a Distributed Application Bundle from Docker Compose and deploy it as Docker Stack in [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/docker-services-stack-distributed-application-bundle\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2017-01-06T07:06:54+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-11-17T16:43:26+00:00\" \/>\n<meta name=\"author\" content=\"Arun Gupta, VP, Developer Advocacy, Couchbase\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@arungupta\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Arun Gupta, VP, Developer Advocacy, Couchbase\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/docker-services-stack-distributed-application-bundle\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/docker-services-stack-distributed-application-bundle\/\"},\"author\":{\"name\":\"Arun Gupta, VP, Developer Advocacy, Couchbase\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/39d8caed0f536489b6aa6e8d31ee631f\"},\"headline\":\"Docker Services, Stack and Distributed Application Bundle\",\"datePublished\":\"2017-01-06T07:06:54+00:00\",\"dateModified\":\"2023-11-17T16:43:26+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/docker-services-stack-distributed-application-bundle\/\"},\"wordCount\":1146,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/docker-services-stack-distributed-application-bundle\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/docker-services-stack-distributed-application-bundle\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/docker-services-stack-distributed-application-bundle\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/docker-services-stack-distributed-application-bundle\/\",\"name\":\"Docker Services, Stack & Distributed Application Bundle\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/docker-services-stack-distributed-application-bundle\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/docker-services-stack-distributed-application-bundle\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"datePublished\":\"2017-01-06T07:06:54+00:00\",\"dateModified\":\"2023-11-17T16:43:26+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/docker-services-stack-distributed-application-bundle\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/docker-services-stack-distributed-application-bundle\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/docker-services-stack-distributed-application-bundle\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"width\":1800,\"height\":630},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/docker-services-stack-distributed-application-bundle\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Docker Services, Stack and Distributed Application Bundle\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"width\":218,\"height\":34,\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/39d8caed0f536489b6aa6e8d31ee631f\",\"name\":\"Arun Gupta, VP, Developer Advocacy, Couchbase\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/8900a75409c646948fe0bd80f6240337\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/f912e10b5f39748ee4f1a0b0da6f42747f0b3a94fe7acb511791468656f5e726?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/f912e10b5f39748ee4f1a0b0da6f42747f0b3a94fe7acb511791468656f5e726?s=96&d=mm&r=g\",\"caption\":\"Arun Gupta, VP, Developer Advocacy, Couchbase\"},\"description\":\"Arun Gupta is the vice president of developer advocacy at Couchbase. He has built and led developer communities for 10+ years at Sun, Oracle, and Red Hat. He has deep expertise in leading cross-functional teams to develop and execute strategy, planning and execution of content, marketing campaigns, and programs. Prior to that he led engineering teams at Sun and is a founding member of the Java EE team. Gupta has authored more than 2,000 blog posts on technology. He has extensive speaking experience in more than 40 countries on myriad topics and is a JavaOne Rock Star for three years in a row. Gupta also founded the Devoxx4Kids chapter in the US and continues to promote technology education among children. An author of several books on technology, an avid runner, a globe trotter, a Java Champion, a JUG leader, NetBeans Dream Team member, and a Docker Captain, he is easily accessible at @arungupta.\",\"sameAs\":[\"https:\/\/x.com\/arungupta\"],\"url\":\"https:\/\/www.couchbase.com\/blog\/author\/arun-gupta\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Docker Services, Stack & Distributed Application Bundle","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.couchbase.com\/blog\/docker-services-stack-distributed-application-bundle\/","og_locale":"en_US","og_type":"article","og_title":"Docker Services, Stack and Distributed Application Bundle","og_description":"First Release Candidate of Docker 1.12 was announced over two weeks ago. Several new features are planned for this release. This blog will show\u00a0how to create a Distributed Application Bundle from Docker Compose and deploy it as Docker Stack in [&hellip;]","og_url":"https:\/\/www.couchbase.com\/blog\/docker-services-stack-distributed-application-bundle\/","og_site_name":"The Couchbase Blog","article_published_time":"2017-01-06T07:06:54+00:00","article_modified_time":"2023-11-17T16:43:26+00:00","author":"Arun Gupta, VP, Developer Advocacy, Couchbase","twitter_card":"summary_large_image","twitter_creator":"@arungupta","twitter_misc":{"Written by":"Arun Gupta, VP, Developer Advocacy, Couchbase","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/docker-services-stack-distributed-application-bundle\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/docker-services-stack-distributed-application-bundle\/"},"author":{"name":"Arun Gupta, VP, Developer Advocacy, Couchbase","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/39d8caed0f536489b6aa6e8d31ee631f"},"headline":"Docker Services, Stack and Distributed Application Bundle","datePublished":"2017-01-06T07:06:54+00:00","dateModified":"2023-11-17T16:43:26+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/docker-services-stack-distributed-application-bundle\/"},"wordCount":1146,"commentCount":0,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/docker-services-stack-distributed-application-bundle\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/docker-services-stack-distributed-application-bundle\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/docker-services-stack-distributed-application-bundle\/","url":"https:\/\/www.couchbase.com\/blog\/docker-services-stack-distributed-application-bundle\/","name":"Docker Services, Stack & Distributed Application Bundle","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/docker-services-stack-distributed-application-bundle\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/docker-services-stack-distributed-application-bundle\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","datePublished":"2017-01-06T07:06:54+00:00","dateModified":"2023-11-17T16:43:26+00:00","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/docker-services-stack-distributed-application-bundle\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/docker-services-stack-distributed-application-bundle\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/docker-services-stack-distributed-application-bundle\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","width":1800,"height":630},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/docker-services-stack-distributed-application-bundle\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Docker Services, Stack and Distributed Application Bundle"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"The Couchbase Blog","description":"Couchbase, the NoSQL Database","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"The Couchbase Blog","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","width":218,"height":34,"caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/39d8caed0f536489b6aa6e8d31ee631f","name":"Arun Gupta, VP, Developer Advocacy, Couchbase","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/8900a75409c646948fe0bd80f6240337","url":"https:\/\/secure.gravatar.com\/avatar\/f912e10b5f39748ee4f1a0b0da6f42747f0b3a94fe7acb511791468656f5e726?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/f912e10b5f39748ee4f1a0b0da6f42747f0b3a94fe7acb511791468656f5e726?s=96&d=mm&r=g","caption":"Arun Gupta, VP, Developer Advocacy, Couchbase"},"description":"Arun Gupta is the vice president of developer advocacy at Couchbase. He has built and led developer communities for 10+ years at Sun, Oracle, and Red Hat. He has deep expertise in leading cross-functional teams to develop and execute strategy, planning and execution of content, marketing campaigns, and programs. Prior to that he led engineering teams at Sun and is a founding member of the Java EE team. Gupta has authored more than 2,000 blog posts on technology. He has extensive speaking experience in more than 40 countries on myriad topics and is a JavaOne Rock Star for three years in a row. Gupta also founded the Devoxx4Kids chapter in the US and continues to promote technology education among children. An author of several books on technology, an avid runner, a globe trotter, a Java Champion, a JUG leader, NetBeans Dream Team member, and a Docker Captain, he is easily accessible at @arungupta.","sameAs":["https:\/\/x.com\/arungupta"],"url":"https:\/\/www.couchbase.com\/blog\/author\/arun-gupta\/"}]}},"authors":[{"term_id":8933,"user_id":58,"is_guest":0,"slug":"arun-gupta","display_name":"Arun Gupta, VP, Developer Advocacy, Couchbase","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/f912e10b5f39748ee4f1a0b0da6f42747f0b3a94fe7acb511791468656f5e726?s=96&d=mm&r=g","author_category":"","last_name":"Gupta","first_name":"Arun","job_title":"","user_url":"","description":"Arun Gupta is the vice president of developer advocacy at Couchbase. He has built and led developer communities for 10+ years at Sun, Oracle, and Red Hat. He has deep expertise in leading cross-functional teams to develop and execute strategy, planning and execution of content, marketing campaigns, and programs. Prior to that he led engineering teams at Sun and is a founding member of the Java EE team.\r\n\r\nGupta has authored more than 2,000 blog posts on technology. He has extensive speaking experience in more than 40 countries on myriad topics and is a JavaOne Rock Star for three years in a row. Gupta also founded the Devoxx4Kids chapter in the US and continues to promote technology education among children. An author of several books on technology, an avid runner, a globe trotter, a Java Champion, a JUG leader, NetBeans Dream Team member, and a Docker Captain, he is easily accessible at @arungupta."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/2319","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/users\/58"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/comments?post=2319"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/2319\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media\/13873"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media?parent=2319"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/categories?post=2319"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/tags?post=2319"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/ppma_author?post=2319"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}