Objectives
We will
- Create a docker image and push it to docker hub
- Pull the image from the hub and create a stack.
Procedures
First I created a directory as below.
$ mkdir docker-stack-tutorial
We will create the Dockerfile
, and some python scripts.
The directory should look like below.
$ tree
.
├── Dockerfile
├── app.py
└── requirements.txt
0 directories, 3 files
The dockerfile is as below.
# Dockerfile
FROM python:3.7
WORKDIR /app
ADD . /app
RUN pip install -r requirements.txt
EXPOSE 80
ENV NAME World
CMD ["python", "app.py"]
app.py for python is written as below.
# app.py
from flask import Flask
from redis import Redis, RedisError
import os
import socket
# Connect to Redis
redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)
app = Flask(__name__)
@app.route("/")
def hello():
try:
visits = redis.incr('counter')
except RedisError:
visits = "<i>cannot connect to Redis, counter disabled</i>"
html = "<h3>Hello {name}!</h3>" \
"<b>Hostname:</b> {hostname}<br/>" \
"<b>Visits:</b> {visits}"
return html.format(name=os.getenv('NAME', "world"), hostname=socket.gethostname(), visits=visits)
if __name__ == "__main__":
app.run(host='0.0.0.0', port=80)
Finally, the requirements.txt is:
# requirements.txt
Flask
Redis
Now we will build and run the docker image.
$ docker build -t python-server .
Sending build context to Docker daemon 5.12kB
Step 1/7 : FROM python:3.7
---> 5c1cd4638fb7
............
$ docker run -p 4000:80 python-server
* Serving Flask app "app" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://0.0.0.0:80/ (Press CTRL+C to quit)
Go to localhost:4000
and you should see this page (For some reason, redis was not working.):
We see that the container id is 99f360ce0c36
here. We will commit the image, and push it to docker hub.
$ docker login
Authenticating with existing credentials...
Login Succeeded
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
99f360ce0c36 python-server "python app.py" About a minute ago Up About a minute 0.0.0.0:4000->80/tcp keen_galois
$ docker commit 99f360ce0c36 python-server:latest
sha256:9dbcf7df033bb595c6e4c6528dd125716f11355d43dcea4dc8ccbaaced38c44c
$ docker tag python-server:latest USERNAME/python-server:latest
$ docker push USERNAME/python-server:latest
Now we will create our docker-compose.yml
file.
version: "3"
services:
web:
image: USERNAME/python-server:latest
deploy:
replicas: 5
resources:
limits:
cpus: "0.1"
memory: 50M
restart_policy:
condition: on-failure
ports:
- "80:80"
networks:
- webnet
networks:
webnet:
We will initialize the swarm and deploy it.
$ docker swarm init
Swarm initialized: current node (nrgwdwv97ioguu0gqq7t19kln) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-3lcxtiaau24gw21h2bgkd1ptavl56yczedbcm7d4e865naj8ks-7c5sgf7jh4youa7xsq2l3dt3j 192.168.65.3:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
$ docker stack deploy -c docker-compose.yml getstartedexample
Creating network getstartedexample_webnet
Creating service getstartedexample_web
We can see all the nodes here using ps
.
$ docker stack ps getstartedexample
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
x3xradislkhr getstartedexample_web.1 USERNAME/python-server:latest docker-desktop Running Running 12 seconds ago
shlygtlq66e0 getstartedexample_web.2 USERNAME/python-server:latest docker-desktop Running Running 12 seconds ago
uk1wexhimc8a getstartedexample_web.3 USERNAME/python-server:latest docker-desktop Running Running 12 seconds ago
rijovk7yzr48 getstartedexample_web.4 USERNAME/python-server:latest docker-desktop Running Running 12 seconds ago
avlqa3hxgbt2 getstartedexample_web.5 USERNAME/python-server:latest docker-desktop Running Running 12 seconds ago
When you access localhost
, you should see the node ids every time you refresh.
Use the command below to exit.
$ docker stack rm getstartedexample
Removing service getstartedexample_web
Removing network getstartedexample_webnet
Top comments (0)