Docker

What is container?

"A container image is a lightweight, standalone, executable package of software that includes everything needed to run an application: code, run-time, system tools, system libraries and settings." - docker.com

First Docker App

Find the base operating system

$ uname -a

Linux 668a632cd1bc 4.15.0-30-generic #32~16.04.1-Ubuntu SMP Thu Jul 26 20:25:39 UTC 2018 x86_64 GNU/Linux


$ lsb_release -a

No LSB modules are available.

Distributor ID: Ubuntu

Description: Ubuntu 16.04.5 LTS

Release: 16.04

Codename: xenial


Install docker

Using the instruction in the link below

https://docs.docker.com/install/linux/docker-ce/ubuntu/#install-using-the-repository


Check docker version

$ docker --version

Docker version 18.06.0-ce, build 0ffa825


Docker commands:

docker build -t friendlyhello . # Create image using this directory's Dockerfile

docker run -p 4000:80 friendlyhello # Run "friendlyname" mapping port 4000 to 80

docker run -d -p 4000:80 friendlyhello # Same thing, but in detached mode

docker container ls # List all running containers

docker container ls -a # List all containers, even those not running

docker container stop <hash> # Gracefully stop the specified container

docker container kill <hash> # Force shutdown of the specified container

docker container rm <hash> # Remove specified container from this machine

docker container rm $(docker container ls -a -q) # Remove all containers

docker image ls -a # List all images on this machine

docker image rm <image id> # Remove specified image from this machine

docker image rm $(docker image ls -a -q) # Remove all images from this machine

docker login # Log in this CLI session using your Docker credentials

docker tag <image> username/repository:tag # Tag <image> for upload to registry

docker push username/repository:tag # Upload tagged image to registry

docker run username/repository:tag # Run image from a registry


View the docker images

$ sudo docker images

REPOSITORY TAG IMAGE ID CREATED SIZE


Test your docker with hello-world. If you see the output as below, you are good to go.

$ docker run -it hello-world

Unable to find image 'hello-world:latest' locally

latest: Pulling from library/hello-world

9db2ca6ccae0: Pull complete

Digest: sha256:4b8ff392a12ed9ea17784bd3c9a8b1fa3299cac44aca35a85c90c5e3c7afacdc

Status: Downloaded newer image for hello-world:latest


Hello from Docker!

This message shows that your installation appears to be working correctly.


To generate this message, Docker took the following steps:

1. The Docker client contacted the Docker daemon.

2. The Docker daemon pulled the "hello-world" image from the Docker Hub.

(amd64)

3. The Docker daemon created a new container from that image which runs the

executable that produces the output you are currently reading.

4. The Docker daemon streamed that output to the Docker client, which sent it

to your terminal.


To try something more ambitious, you can run an Ubuntu container with:

$ docker run -it ubuntu bash


Share images, automate workflows, and more with a free Docker ID:

https://hub.docker.com/


For more examples and ideas, visit:

https://docs.docker.com/engine/userguide/


Create a directory with the follow directory structure and contents of the file are also below.

$ tree ~/docker-app

docker-app

├── docker-compose.yml

└── flask-app

├── app.py

├── Dockerfile

└── requirements.txt


Create a Docker file. Docker file contains the instruction for docker image.

$ cat ~/docker-app/flask-app/Dockerfile

FROM ubuntu:latest

RUN apt-get update -y && apt-get install -y python-pip python-dev build-essential

COPY . /app

WORKDIR /app

RUN pip install -r requirements.txt

CMD ["python", "app.py"]


Python libraries to be installed using pip. Here we require Flask for web application using python.

$ cd

$ cat ~/docker-app/flask-app/requirements.txt

Flask==1.0.2

cassandra-driver


$ cat ~/docker-app/flask-app/app.py

from flask import Flask

app = Flask(__name__)


count = 0


@app.route("/", methods = ["get", "post"])

def hello():

return "Hello world!"


@app.route("/counter")

def counter():

global count

count += 1

return str(count)


if __name__ == "__main__":

app.run(debug = True, host = "0.0.0.0", port = 5000)


Go inside the flask-app directory and build the local copy of the image

$ cd ~/docker-app/flask-app/

$ sudo docker build -t flask-sample:latest .

Sending build context to Docker daemon 3.072kB

Step 1/8 : FROM ubuntu:latest

latest: Pulling from library/ubuntu

c64513b74145: Pull complete

01b8b12bad90: Pull complete

c5d85cf7a05f: Pull complete

b6b268720157: Pull complete

e12192999ff1: Pull complete

Digest: sha256:3f119dc0737f57f704ebecac8a6d8477b0f6ca1ca0332c7ee1395ed2c6a82be7

Status: Downloaded newer image for ubuntu:latest

---> 735f80812f90

Step 2/8 : RUN apt-get update -y

---> Running in d3b9b1c77b39

Get:1 http://security.ubuntu.com/ubuntu bionic-security InRelease [83.2 kB]

Get:2 http://archive.ubuntu.com/ubuntu bionic InRelease [242 kB]

Get:3 http://security.ubuntu.com/ubuntu bionic-security/universe Sources [14.3 kB]

...


Downloading https://files.pythonhosted.org/packages/4d/de/32d741db316d8fdb7680822dd37001ef7a448255de9699ab4bfcbdf4172b/MarkupSafe-1.0.tar.gz

Building wheels for collected packages: itsdangerous, MarkupSafe

Running setup.py bdist_wheel for itsdangerous: started

Running setup.py bdist_wheel for itsdangerous: finished with status 'done'

Stored in directory: /root/.cache/pip/wheels/2c/4a/61/5599631c1554768c6290b08c02c72d7317910374ca602ff1e5

Running setup.py bdist_wheel for MarkupSafe: started

Running setup.py bdist_wheel for MarkupSafe: finished with status 'done'

Stored in directory: /root/.cache/pip/wheels/33/56/20/ebe49a5c612fffe1c5a632146b16596f9e64676768661e4e46

Successfully built itsdangerous MarkupSafe

Installing collected packages: Werkzeug, click, MarkupSafe, Jinja2, itsdangerous, Flask

Successfully installed Flask-1.0.2 Jinja2-2.10 MarkupSafe-1.0 Werkzeug-0.14.1 click-6.7 itsdangerous-0.24

Removing intermediate container 9e95964fae77

---> 631959518f29

Step 7/8 : ENTRYPOINT ["python"]

---> Running in 3bef8b04e02e

Removing intermediate container 3bef8b04e02e

---> 43005e09038a

Step 8/8 : CMD ["app.py"]

---> Running in 467b15172bff

Removing intermediate container 467b15172bff

---> 0ef49eefb5b5

Successfully built 0ef49eefb5b5

Successfully tagged flask-sample:latest



Find the local copies of the images.

$ sudo docker image ls

REPOSITORY TAG IMAGE ID CREATED SIZE

flask-sample latest 08106c7a59e7 About a minute ago 468MB

ubuntu latest 735f80812f90 2 weeks ago 83.5MB


Run the container in detached mode (argument -d).

$ sudo docker run -d -p 5000:5000 flask-sample

c9e070076aa65f1014960b4e625c75d737042aa2ed0ef1c90ef2f9d7a06a4502


$ sudo docker ps -a

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

c9e070076aa6 flask-sample "python app.py" 4 seconds ago Up 3 seconds 0.0.0.0:5000->5000/tcp epic_heisenberg



View the log. -f at the end tails the log to the console.

$ sudo docker logs c9e070076aa6 -f

* Serving Flask app "app" (lazy loading)

* Environment: production

WARNING: Do not use the development server in a production environment.

Use a production WSGI server instead.

* Debug mode: on

* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)

* Restarting with stat

* Debugger is active!

* Debugger PIN: 236-035-556

...


Test the web page

$ curl http://localhost:5000

Hello world!


If you want to bash terminal

$ sudo docker exec -it c9e070076aa6 bash


Inspect docker container

$ sudo docker inspect c9e070076aa6

[

{

"Id": "465c38e956c54f8058d3ebfdc183ff0fa9e18472b839dd3c5a24db4cbecc4396",

"Created": "2018-08-12T16:25:03.053918463Z",

"Path": "python",

"Args": [

"app.py"

],

"State": {

"Status": "running",

"Running": true,

"Paused": false,

"Restarting": false,

"OOMKilled": false,

"Dead": false,

"Pid": 6776,

"ExitCode": 0,

"Error": "",

"StartedAt": "2018-08-12T17:34:00.395255705Z",

"FinishedAt": "2018-08-12T17:17:45.173095557Z"

},

....



Stop the docker container

$ sudo docker stop c9e070076aa6


Check the status of the containers. The container is in exited state.

$ sudo docker ps -a

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

c9e070076aa6 flask-sample "python app.py" 20 minutes ago Exited (0) 6 seconds ago epic_heisenberg



If you want to start the stopped container, run the following command.

$ sudo docker container start c9e070076aa6

c9e070076aa6


Stop the container, delete the container and delete the docker image

$ sudo docker stop c9e070076aa6

$ sudo docker container rm c9e070076aa6

$ sudo docker ps -a

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

$ sudo docker image rm flask-sample

Untagged: flask-sample:latest

Deleted: sha256:34eb09e6c97440208aa3b1ac3acd7cf1de8dc3098c314703f357f1a3c25f0457

Deleted: sha256:99e81e9f7fb1166e2e3ddb04c687d8a5e25db3728811a9c4cb772cab6e780ba9

Deleted: sha256:f96de24162fc365a0bdd4a9c88865f82ffc9e566253a92bad44e7c0bcc1de992

Deleted: sha256:f5997e0a9e5b55e3f4f438f1af8279af2bb5cf7bc6aff7aa9b9e4f8f2ee740d9

Deleted: sha256:c99064ae31c213ca213ee123d1afd3828bf9c982aa936a8dcce32ed0ad176b2c

Deleted: sha256:c4f6bbd734d7c3fd168e6a88e7ba8803e26477982bc8dc886c70a8c37a4ea9da

Deleted: sha256:06e71bb9cbb6cce78e58025885f62aa37530274bcfa7aff46912c40641da89ed

Deleted: sha256:a01ce400d3d13ee2706623550cb33d666b9dd23a57d77e332ea605a4dcca082e

Deleted: sha256:37b99233e7f0b0aa6d39157c6d2d1e5ca6ba516bd0d8dce296f2ab820e0f7bf0

Deleted: sha256:8617ef7db4290cd64f881e546db763edc7c2e4e207dbb356e9330d0cbdc99172

Deleted: sha256:1aab5a8ea148fff8394329f1e31995ad395aa5f04adf7e2d842d42c92593d438



Publish image to docker hub

If you do not user account, sign up hub.docker.org

Create a tag. This is ultimately be in used in docker hub.

$ sudo docker tag flask-sample:latest abasar/web-app:1.0

$ sudo docker image ls

REPOSITORY TAG IMAGE ID CREATED SIZE

flask-sample latest 34f43e4e623c 10 minutes ago 468MB

abasar/web-app 1.0 34f43e4e623c 10 minutes ago 468MB

ubuntu latest 735f80812f90 2 weeks ago 83.5MB


Login to push the image to docker hub.

$ sudo docker login

Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.

Username: <your hub.docker.org username>

Password: <your hub.docker.org password>

WARNING! Your password will be stored unencrypted in /home/training/.docker/config.json.

Configure a credential helper to remove this warning. See

https://docs.docker.com/engine/reference/commandline/login/#credentials-store


Login Succeeded



Push the image to docker hub.

$ sudo docker push abasar/web-app:1.0

The push refers to repository [docker.io/abasar/web-app]

435ae6a71b97: Pushed

9f5518f577d2: Pushed

e88cdd645a03: Pushed

268a067217b5: Pushed

c01d74f99de4: Pushed

ccd4d61916aa: Pushed

8f2b771487e9: Pushed

f49017d4d5ce: Mounted from library/ubuntu

1.0: digest: sha256:6e41e43ff2264abeb361a8fd3e300991b77fc619b98842459795fec1d32d39f4 size: 1988


You can test the image that you just created by pulling from docker hub.

$ sudo docker pull abasar/web-app:1.0

1.0: Pulling from abasar/web-app

c64513b74145: Already exists

01b8b12bad90: Already exists

c5d85cf7a05f: Already exists

b6b268720157: Already exists

e12192999ff1: Already exists

c1f77516f7b5: Already exists

4f1baabdad3a: Already exists

bcf0e2b1cc0d: Already exists

Digest: sha256:6e41e43ff2264abeb361a8fd3e300991b77fc619b98842459795fec1d32d39f4

Status: Downloaded newer image for abasar/web-app:1.0



See the images

$ sudo docker images

REPOSITORY TAG IMAGE ID CREATED SIZE

abasar/web-app 1.0 34f43e4e623c 18 minutes ago 468MB


Run the custom built image that you just pulled from docker hub.

$ sudo docker run -p 5000:5000 abasar/web-app:1.0

* Serving Flask app "app" (lazy loading)

* Environment: production

WARNING: Do not use the development server in a production environment.

Use a production WSGI server instead.

* Debug mode: on

* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)

* Restarting with stat

* Debugger is active!

* Debugger PIN: 236-035-556


Docker Compose


Install docker-compose following instructions

https://docs.docker.com/compose/install/


Essentially, you have to run the following two commands

$ sudo curl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose

$ sudo chmod +x /usr/local/bin/docker-compose

Check the version

$ docker-compose --version

docker-compose version 1.22.0, build f46880fe


Create docker-compose.yml file. For location, refer the directory tree below.

$ cat ~/docker-app/docker-compose.yml

version: "3"

services:

web:

build: ./flask-app

ports:

- "5000:5000"

volumes:

- "./flask-app:/app"

ports:

- "5000:5000"

networks:

- webnet

networks:

webnet:


Directory tree

$ tree ~/docker-app

/home/training/docker-app

├── docker-compose.yml

└── flask-app

├── app.py

├── Dockerfile

└── requirements.txt


Bring up the container using docker compose

$ sudo docker-compose build

$ sudo docker-compose up

Starting docker-app_web_1 ... done

Attaching to docker-app_web_1

web_1 | * Serving Flask app "app" (lazy loading)

web_1 | * Environment: production

web_1 | WARNING: Do not use the development server in a production environment.

web_1 | Use a production WSGI server instead.

web_1 | * Debug mode: on

web_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)

web_1 | * Restarting with stat

web_1 | * Debugger is active!

web_1 | * Debugger PIN: 294-308-829



Reset docker environment

Stop all containers

$ docker stop $(docker ps -a -q)

Remove all containers

$ docker rm $(docker ps -a -q)

Remove all images

$ docker rmi -f $(docker images -a -q)

Delete all volumes

$ docker volume rm $(docker volume ls -q)