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)