Docker and docker-compose
Table Of Contents
$ HOSTNAME=demo FLASK_APP=src/primes_server.py flask run
* Serving Flask app "src/primes_server.py"
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
Open another terminal and then:
$ curl http://127.0.0.1:5000/primes/check/3
{"isPrime": true, "hostname": "demo", "number": 3}
$ curl http://127.0.0.1:5000/primes/check/4
{"isPrime": false, "hostname": "demo", "number": 4}
It’s basically about installing the required Python module Flask, adding the python
server to the image and defining the command on how to run the server when the Docker container
for this image is started.
docker build -t demo/primes-server:latest . -f images/Dockerfile.primes_server
$ docker run --rm --name=primes-server -p 5000:5000 -d demo/primes-server:latest
$ curl http://localhost:5000/primes/check/3
{"isPrime": true, "hostname": "09d6af743a3f", "number": 3}
$ curl http://localhost:5000/primes/check/4
{"isPrime": false, "hostname": "09d6af743a3f", "number": 4}
When stopping the server (docker stop primes-server
) the container automatically
goes away because of the --rm
option.
$ docker-compose -f compose/docker-compose-server.yml up -d primes-server
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
29177c0471cf demo/primes-server:latest "flask run --host=0.…" About a minute ago Up About a minute 0.0.0.0:5000->5000/tcp docker-compose-demo_primes-server_1
$ curl http://localhost:5000/primes/check/3
{"isPrime": true, "hostname": "09d6af743a3f", "number": 3}
$ curl http://localhost:5000/primes/check/4
{"isPrime": false, "hostname": "09d6af743a3f", "number": 4}
The -d
is that docker compose starts the process into background.
Avoiding that more services are started the service prime-service is specified.
You can shutdown with docker-compose -f compose/docker-compose-server.yml down
.
$ docker-compose --compatibility -f compose/docker-compose-loadbalancer.yml up -d
Starting compose_primes-server_1 ... done
Starting compose_primes-server_2 ... done
Starting compose_primes-server_3 ... done
Starting compose_proxy_1 ... done
$ for n in $(seq 1 12); do echo "$(curl -s http://localhost/primes/check/$n)"; done
{"isPrime": false, "hostname": "99a5669c6fa2", "number": 1}
{"isPrime": true, "hostname": "35eeb727e120", "number": 2}
{"isPrime": true, "hostname": "ffda7cf2c91f", "number": 3}
{"isPrime": false, "hostname": "99a5669c6fa2", "number": 4}
{"isPrime": true, "hostname": "35eeb727e120", "number": 5}
{"isPrime": false, "hostname": "ffda7cf2c91f", "number": 6}
{"isPrime": true, "hostname": "99a5669c6fa2", "number": 7}
{"isPrime": false, "hostname": "35eeb727e120", "number": 8}
{"isPrime": false, "hostname": "ffda7cf2c91f", "number": 9}
{"isPrime": false, "hostname": "99a5669c6fa2", "number": 10}
{"isPrime": true, "hostname": "35eeb727e120", "number": 11}
{"isPrime": false, "hostname": "ffda7cf2c91f", "number": 12}
--compatibility
parameter is required otherwise the scale featuredocker-compose --compatibility -f compose/docker-compose-loadbalancer.yml down
.
docker-compose --compatibility -f compose/docker-compose-loadbalancer.yml up -d --scale=primes-server=10
Starting compose_primes-server_1 ... done
Starting compose_primes-server_2 ... done
Starting compose_primes-server_3 ... done
Creating compose_primes-server_4 ... done
Creating compose_primes-server_5 ... done
Creating compose_primes-server_6 ... done
Creating compose_primes-server_7 ... done
Creating compose_primes-server_8 ... done
Creating compose_primes-server_9 ... done
Creating compose_primes-server_10 ... done
compose_proxy_1 is up-to-date
The health check can be implemented as REST call of the server.
The server has to tell whether all is fine.
$ docker ps --format="{{.Names}} {{.Status}}"
compose_proxy_1 Up 43 seconds
compose_primes-server_3 Up 45 seconds (healthy)
compose_primes-server_2 Up 45 seconds (healthy)
compose_primes-server_1 Up 46 seconds (healthy)
In the logs of each container you see a record each
10 seconds:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:5000/status"]
interval: 10s
timeout: 2s
Starting a Mongo database via Docker:
$ docker run --rm --name=mongo -p 27017:27017 -d mongo:latest
Using the previously started Docker container:
$ MONGODB_HOST=localhost HOSTNAME=demo FLASK_APP=src/primes_server_mongo.py flask run
This prime server stores each calculated primes for a given maximum number into
Mongo DB and next time when same list is requested the list is queried in the database
and returnd instead of the calculation.
The docker image can be built with
$ docker build -t demo/primes-server-mongo:latest . -f images/Dockerfile.primes_server_mongo
With this you can also run an environment with Mongo DB, three primes server and
a loadbalance in front of this:
$ docker-compose --compatibility -f compose/docker-compose-mongo.yml up -d
Using curl then only difference now is that (currently) the port is 80 (loadbalancer).
$ curl http://127.0.0.1:80/primes/list/100
{"max_n": 100, "primes": [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97], "hostname": "383ac2648957"}
You also can verify it changing into the Mongo DB Docker container:
$ docker exec -it compose_mongodb_1 bash
$ mongo
$ use primes
switched to db primes
$ db.Primes.find({max_n: 100})
{ "_id" : ObjectId("5bb4aa1a667cd800012a95d0"), "max_n" : 100, "values" : [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67,71, 73, 79, 83, 89, 97 ] }