Docker 101

A beginner’s guide to containerization

Definition

Goals

Prerequisites

Advantages of Containers over traditional VMs

Getting Started on Ubuntu:

$ sudo apt-get update
$ sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
$ sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io

Getting Started on Windows:

Hello World!

$ docker run hello-world

Creating your own images and containers

from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World!"
if __name__ == "__main__":
app.run(debug=True, host="0.0.0.0")
# Inherit from the Python Docker image
FROM python:3.7-slim
# Install the Flask package via pip
RUN pip install flask==1.0.2
# Copy the source code to app folder
COPY ./app.py /app/
# Change the working directory
WORKDIR /app/
# Set “python” as the entry point
ENTRYPOINT [“python”]
# Set the command as the script name
CMD [“app.py”]
$ docker build -t flask_app:0.1 .
$ docker images
REPOSITORY   TAG       IMAGE ID      CREATED       SIZE
flask_app 0.1 c6eb89fefb25 2 minutes ago 153MB
python 3.7-slim 4c2534c95211 4 weeks ago 143MB
$ docker run -d -p 5000:5000 — name simple_flask flask_app:0.1 
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED
03c650a4eb58 flask_app:0.1 "python app.py" 16 seconds ago
STATUS PORTS NAMES
Up 3 seconds 0.0.0.0:5000->5000/tcp simple_flask
 $ docker stop simple_flask
 $ docker rm simple_flask
$ docker rmi flask_app:0.1

Docker Hub | Docker Pull | Docker Push

$ docker pull <image:tag>
$ docker login
$ docker push <image_name:tag>
$ docker push <private_repo_name:tag>
$ docker tag rhel-httpd registry-host:5000/myadmin/rhel-httpd
$ docker images
$ docker push registry-host:5000/myadmin/rhel-httpd

Docker Compose

Step 1: Setup the code base

import time

import redis
from flask import Flask

app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)


def get_hit_count():
retries = 5
while True:
try:
return cache.incr('hits')
except redis.exceptions.ConnectionError as exc:
if retries == 0:
raise exc
retries -= 1
time.sleep(0.5)


@app.route('/')
def hello():
count = get_hit_count()
return 'Hello World! I have been seen {} times.\n'.format(count)
flask
redis

Step 2: Creating a Dockerfile:

FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP app.py
ENV FLASK_RUN_HOST 0.0.0.0
RUN apk add — no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
COPY . .
CMD ["flask", "run"]

Step 3: Define services in a compose file

version: '3'
services:
web:
build: .
ports:
- "5000:5000"
volumes:
- .:/code
environment:
FLASK_ENV: development
redis:
image: "redis:alpine"

Web service

Redis service

Bonus point:
Volumes

Step 4: Build and run your app with Compose

$ docker-compose up
Creating network "composetest_default" with the default driver
Creating composetest_web_1 ...
Creating composetest_redis_1 ...
Creating composetest_web_1
Creating composetest_redis_1 ... done
Attaching to composetest_web_1, composetest_redis_1
web_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
...
Hello World! I have been seen 1 times.
docker inspect <tag or id>

Step 5: Updating the application on the fly

return ‘Hello from Docker! I have been seen {} times.\n’.format(count)

Other Docker Compose commands

$ docker-compose run web env
$ docker-compose stop
$ docker-compose down --volumes

Bonus Step:

Scaling up your app!

web:
build: .
command: python app.py
ports:
- "5000"
volumes:
- .:/code
links:
- redis
redis:
image: redis
$ docker-compose up -d
$ docker-compose psName             Command                     State Ports
compose_redis_1 /entrypoint.sh redis-server Up 6379/tcp
compose_web_1 python app.py Up 0.0.0.0:32768->5000/tcp
docker-compose scale web=10
docker-compose stop
docker-compose rm

Summary

Every company is a software company; even if it’s not in the software business