1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
<h1>Deploy a stack to a swarm</h1>
<p>When running Docker Engine in swarm mode, you can use <code class="language-plaintext highlighter-rouge">docker stack deploy</code> to deploy a complete application stack to the swarm. The <code class="language-plaintext highlighter-rouge">deploy</code> command accepts a stack description in the form of a <a href="../../../compose/compose-file/compose-file-v3/index">Compose file</a>.</p> <p>The <code class="language-plaintext highlighter-rouge">docker stack deploy</code> command supports any Compose file of version “3.0” or above. If you have an older version, see the <a href="../../../compose/compose-file/compose-versioning/index#upgrading">upgrade guide</a>.</p> <p>To run through this tutorial, you need:</p> <ol> <li> <p>A Docker Engine running in <a href="../swarm-mode/index">swarm mode</a>. If you’re not familiar with swarm mode, you might want to read <a href="../key-concepts/index">Swarm mode key concepts</a> and <a href="../how-swarm-mode-works/services/index">How services work</a>.</p> <blockquote> <p><strong>Note</strong></p> <p>If you’re trying things out on a local development environment, you can put your engine into swarm mode with <code class="language-plaintext highlighter-rouge">docker swarm init</code>.</p> <p>If you’ve already got a multi-node swarm running, keep in mind that all <code class="language-plaintext highlighter-rouge">docker stack</code> and <code class="language-plaintext highlighter-rouge">docker service</code> commands must be run from a manager node.</p> </blockquote> </li> <li> <p>A current version of <a href="../../../compose/install/index">Docker Compose</a>.</p> </li> </ol> <h2 id="set-up-a-docker-registry">Set up a Docker registry</h2> <p>Because a swarm consists of multiple Docker Engines, a registry is required to distribute images to all of them. You can use the <a href="https://hub.docker.com">Docker Hub</a> or maintain your own. Here’s how to create a throwaway registry, which you can discard afterward.</p> <ol> <li> <p>Start the registry as a service on your swarm:</p> <div class="highlight"><pre class="highlight" data-language="">$ docker service create --name registry --publish published=5000,target=5000 registry:2
</pre></div> </li> <li> <p>Check its status with <code class="language-plaintext highlighter-rouge">docker service ls</code>:</p> <div class="highlight"><pre class="highlight" data-language="">$ docker service ls
ID NAME REPLICAS IMAGE COMMAND
l7791tpuwkco registry 1/1 registry:2@sha256:1152291c7f93a4ea2ddc95e46d142c31e743b6dd70e194af9e6ebe530f782c17
</pre></div> <p>Once it reads <code class="language-plaintext highlighter-rouge">1/1</code> under <code class="language-plaintext highlighter-rouge">REPLICAS</code>, it’s running. If it reads <code class="language-plaintext highlighter-rouge">0/1</code>, it’s probably still pulling the image.</p> </li> <li> <p>Check that it’s working with <code class="language-plaintext highlighter-rouge">curl</code>:</p> <div class="highlight"><pre class="highlight" data-language="">$ curl http://localhost:5000/v2/
{}
</pre></div> </li> </ol> <h2 id="create-the-example-application">Create the example application</h2> <p>The app used in this guide is based on the hit counter app in the <a href="../../../compose/gettingstarted/index">Get started with Docker Compose</a> guide. It consists of a Python app which maintains a counter in a Redis instance and increments the counter whenever you visit it.</p> <ol> <li> <p>Create a directory for the project:</p> <div class="highlight"><pre class="highlight" data-language="">$ mkdir stackdemo
$ cd stackdemo
</pre></div> </li> <li> <p>Create a file called <code class="language-plaintext highlighter-rouge">app.py</code> in the project directory and paste this in:</p> <div class="highlight"><pre class="highlight" data-language="">from flask import Flask
from redis import Redis
app = Flask(__name__)
redis = Redis(host='redis', port=6379)
@app.route('/')
def hello():
count = redis.incr('hits')
return 'Hello World! I have been seen {} times.\n'.format(count)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8000, debug=True)
</pre></div> </li> <li> <p>Create a file called <code class="language-plaintext highlighter-rouge">requirements.txt</code> and paste these two lines in:</p> <pre>flask
redis
</pre> </li> <li> <p>Create a file called <code class="language-plaintext highlighter-rouge">Dockerfile</code> and paste this in:</p> <div class="highlight"><pre class="highlight" data-language=""># syntax=docker/dockerfile:1
FROM python:3.4-alpine
ADD . /code
WORKDIR /code
RUN pip install -r requirements.txt
CMD ["python", "app.py"]
</pre></div> </li> <li> <p>Create a file called <code class="language-plaintext highlighter-rouge">docker-compose.yml</code> and paste this in:</p> <pre>version: "3.9"
services:
web:
image: 127.0.0.1:5000/stackdemo
build: .
ports:
- "8000:8000"
redis:
image: redis:alpine
</pre> <p>The image for the web app is built using the Dockerfile defined above. It’s also tagged with <code class="language-plaintext highlighter-rouge">127.0.0.1:5000</code> - the address of the registry created earlier. This is important when distributing the app to the swarm.</p> </li> </ol> <h2 id="test-the-app-with-compose">Test the app with Compose</h2> <ol> <li> <p>Start the app with <code class="language-plaintext highlighter-rouge">docker-compose up</code>. This builds the web app image, pulls the Redis image if you don’t already have it, and creates two containers.</p> <p>You see a warning about the Engine being in swarm mode. This is because Compose doesn’t take advantage of swarm mode, and deploys everything to a single node. You can safely ignore this.</p> <pre>$ docker-compose up -d
WARNING: The Docker Engine you're using is running in swarm mode.
Compose does not use swarm mode to deploy services to multiple nodes in
a swarm. All containers are scheduled on the current node.
To deploy your application across the swarm, use `docker stack deploy`.
Creating network "stackdemo_default" with the default driver
Building web
...(build output)...
Creating stackdemo_redis_1
Creating stackdemo_web_1
</pre> </li> <li> <p>Check that the app is running with <code class="language-plaintext highlighter-rouge">docker-compose ps</code>:</p> <div class="highlight"><pre class="highlight" data-language="">$ docker-compose ps
Name Command State Ports
-----------------------------------------------------------------------------------
stackdemo_redis_1 docker-entrypoint.sh redis ... Up 6379/tcp
stackdemo_web_1 python app.py Up 0.0.0.0:8000->8000/tcp
</pre></div> <p>You can test the app with <code class="language-plaintext highlighter-rouge">curl</code>:</p> <div class="highlight"><pre class="highlight" data-language="">$ curl http://localhost:8000
Hello World! I have been seen 1 times.
$ curl http://localhost:8000
Hello World! I have been seen 2 times.
$ curl http://localhost:8000
Hello World! I have been seen 3 times.
</pre></div> </li> <li> <p>Bring the app down:</p> <div class="highlight"><pre class="highlight" data-language="">$ docker-compose down --volumes
Stopping stackdemo_web_1 ... done
Stopping stackdemo_redis_1 ... done
Removing stackdemo_web_1 ... done
Removing stackdemo_redis_1 ... done
Removing network stackdemo_default
</pre></div> </li> </ol> <h2 id="push-the-generated-image-to-the-registry">Push the generated image to the registry</h2> <p>To distribute the web app’s image across the swarm, it needs to be pushed to the registry you set up earlier. With Compose, this is very simple:</p> <div class="highlight"><pre class="highlight" data-language="">$ docker-compose push
Pushing web (127.0.0.1:5000/stackdemo:latest)...
The push refers to a repository [127.0.0.1:5000/stackdemo]
5b5a49501a76: Pushed
be44185ce609: Pushed
bd7330a79bcf: Pushed
c9fc143a069a: Pushed
011b303988d2: Pushed
latest: digest: sha256:a81840ebf5ac24b42c1c676cbda3b2cb144580ee347c07e1bc80e35e5ca76507 size: 1372
</pre></div> <p>The stack is now ready to be deployed.</p> <h2 id="deploy-the-stack-to-the-swarm">Deploy the stack to the swarm</h2> <ol> <li> <p>Create the stack with <code class="language-plaintext highlighter-rouge">docker stack deploy</code>:</p> <div class="highlight"><pre class="highlight" data-language="">$ docker stack deploy --compose-file docker-compose.yml stackdemo
Ignoring unsupported options: build
Creating network stackdemo_default
Creating service stackdemo_web
Creating service stackdemo_redis
</pre></div> <p>The last argument is a name for the stack. Each network, volume and service name is prefixed with the stack name.</p> </li> <li> <p>Check that it’s running with <code class="language-plaintext highlighter-rouge">docker stack services stackdemo</code>:</p> <div class="highlight"><pre class="highlight" data-language="">$ docker stack services stackdemo
ID NAME MODE REPLICAS IMAGE
orvjk2263y1p stackdemo_redis replicated 1/1 redis:3.2-alpine@sha256:f1ed3708f538b537eb9c2a7dd50dc90a706f7debd7e1196c9264edeea521a86d
s1nf0xy8t1un stackdemo_web replicated 1/1 127.0.0.1:5000/stackdemo@sha256:adb070e0805d04ba2f92c724298370b7a4eb19860222120d43e0f6351ddbc26f
</pre></div> <p>Once it’s running, you should see <code class="language-plaintext highlighter-rouge">1/1</code> under <code class="language-plaintext highlighter-rouge">REPLICAS</code> for both services. This might take some time if you have a multi-node swarm, as images need to be pulled.</p> <p>As before, you can test the app with <code class="language-plaintext highlighter-rouge">curl</code>:</p> <div class="highlight"><pre class="highlight" data-language="">$ curl http://localhost:8000
Hello World! I have been seen 1 times.
$ curl http://localhost:8000
Hello World! I have been seen 2 times.
$ curl http://localhost:8000
Hello World! I have been seen 3 times.
</pre></div> <p>Thanks to Docker’s built-in routing mesh, you can access any node in the swarm on port 8000 and get routed to the app:</p> <div class="highlight"><pre class="highlight" data-language="">$ curl http://address-of-other-node:8000
Hello World! I have been seen 4 times.
</pre></div> </li> <li> <p>Bring the stack down with <code class="language-plaintext highlighter-rouge">docker stack rm</code>:</p> <div class="highlight"><pre class="highlight" data-language="">$ docker stack rm stackdemo
Removing service stackdemo_web
Removing service stackdemo_redis
Removing network stackdemo_default
</pre></div> </li> <li> <p>Bring the registry down with <code class="language-plaintext highlighter-rouge">docker service rm</code>:</p> <div class="highlight"><pre class="highlight" data-language="">$ docker service rm registry
</pre></div> </li> <li> <p>If you’re just testing things out on a local machine and want to bring your Docker Engine out of swarm mode, use <code class="language-plaintext highlighter-rouge">docker swarm leave</code>:</p> <div class="highlight"><pre class="highlight" data-language="">$ docker swarm leave --force
Node left the swarm.
</pre></div> </li> </ol>
<p><a href="https://docs.docker.com/search/?q=guide">guide</a>, <a href="https://docs.docker.com/search/?q=swarm%20mode">swarm mode</a>, <a href="https://docs.docker.com/search/?q=composefile">composefile</a>, <a href="https://docs.docker.com/search/?q=stack">stack</a>, <a href="https://docs.docker.com/search/?q=compose">compose</a>, <a href="https://docs.docker.com/search/?q=deploy">deploy</a></p>
<div class="_attribution">
<p class="_attribution-p">
© 2019 Docker, Inc.<br>Licensed under the Apache License, Version 2.0.<br>Docker and the Docker logo are trademarks or registered trademarks of Docker, Inc. in the United States and/or other countries.<br>Docker, Inc. and other parties may also have trademark rights in other terms used herein.<br>
<a href="https://docs.docker.com/engine/swarm/stack-deploy/" class="_attribution-link">https://docs.docker.com/engine/swarm/stack-deploy/</a>
</p>
</div>
|