Docker is software program that uses OS Level Virtualization to deliver softwares in packages known as Containers. Containers are isolated from one another with their own libraries, dependencies and can communicate with each other.
Containers vs Virtual Machines :
Source : Docker.com |
A Virtual Machine will have several systems (virtual) running on a same hardware with each system having it's own operating-system. This is achieved using Hypervisor. Because of this architecture, VM's are typically slow to boot.
Source : Docker.com |
Docker on the other hand uses the application level abstraction that packages the code dependencies together. A machine can have multiple containers running together sharing the OS Kernel; each container will run as an isolated seperate process.
Installation :
Docker installation is dependent on the operating system that you are on, this official link has the instructions for your system.
Hello World !
Let's start with Docker by running the "docker run" command, this will try to find the docker image locally, if not found then will pull it from "dockerhub".
% docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
1b930d010525: Pull complete
Digest: sha256:f9dfddf63636d84ef479d645ab5885156ae030f611a56f3a7ac7f2fdd86d7e4e
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
Image is basically a template that can be turned into Container. Docker engine takes image, adds a read-write file system on top, initializes container name, ID, ports etc.
Common commands with Docker
docker images // list all the available images on your system
docker ps // list all running containers
docker ps -a // list all containers
docker run [--name container_name] image_name[:tag_name] // run a docker image and optionally assign a name.
docker logs -f container_id_or_name // view the container log files
docker stop container_id_or_name // stop the container
docker rm container_id_or_name // remove the container
docker rmi image_id_or_name // remove the image
docker rmi $(docker images -a -q) // remove all images
docker stop $(docker ps -q) // stop all the running containers
docker rm $(docker ps -q) // remove all the running containers
Building your own images
In this section, we will create our first docker image. We will be using Flask as an example, let's create the following files inside folder say "docker_demo_flask".
Dockerfile
FROM python:3.8-alpine
MAINTAINER sarbjit
ENV PYTHONUNBUFFERED 1
COPY ./requirements.txt /requirements.txt
RUN pip install -r /requirements.txt
RUN mkdir /src
WORKDIR /src
COPY ./src /src
RUN adduser -D user
USER user
ENTRYPOINT ["python"]
CMD ["app.py"]
Flask>=1.1.2,<1.2.0
src/app.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return 'Hello there'
if __name__ == '__main__':
app.run(debug=True, host="0.0.0.0")
Build the image using the following command (changedir to docker_demo_flask folder first)
docker build -t python-flask-docker:latest .
Here, "-t" specifies the tag-name for the image.
If you do "docker images", you'll see the "python-flask-docker" image available.
Run this image using the following command
docker run -d -p 8000:5000 python-flask-docker
Visit http://127.0.0.1:8000 to view the results
Here, "-d" specifies to run docker container in background (daemeonize it), "-p" is used for port-mapping where the default syntax is Host_Port_No:Container_Port_No (Flask applications by default run on port number 5000, so we are mapping it to port 8000 on our host system).
Docker Volumes :
Once you have build an image, any changes done thereafter in the source code will not be available while running the image unless the image is re-build.
As an example, if we change "Hello there" to "Hello there and where" in "src/app.py", these changes are not reflected while running the image.
We can fix this by using something called Docker volumes. These are like shared drives between container and host system.
Let's re-write our Dockerfile as (Notice the addition of VOLUME)
FROM python:3.8-alpine
MAINTAINER sarbjit
ENV PYTHONUNBUFFERED 1
COPY ./requirements.txt /requirements.txt
RUN pip install -r /requirements.txt
RUN mkdir /src
WORKDIR /src
COPY ./src /src
VOLUME /src
RUN adduser -D user
USER user
ENTRYPOINT ["python"]
CMD ["app.py"]
Once you re-build the docker image, run it with following command by mapping the folder on host system with volume in container.
NOTE : Docker accepts only absoulte path's, so we need to provide absolute host system path.
docker run -d -p 8000:5000 -v `pwd`/src:/src python-flask-docker
Before proceeding further, I want to point out on running commands dynamically. So far you would have noticed that when we start a container, our source code is executed because of ENTRYPOINT and CMD. However, you might want to have your container act as Python virtual environment to have all dependecies resolved and run the commands dynamically.
Our Dockerfile for this scenario would look like :-
FROM python:3.8-alpine
MAINTAINER sarbjit
ENV PYTHONUNBUFFERED 1
COPY ./requirements.txt /requirements.txt
RUN pip install -r /requirements.txt
RUN mkdir /src
WORKDIR /src
COPY ./src /src
VOLUME /src
RUN adduser -D user
USER user
docker run -d -p 8000:5000 -v `pwd`/src:/src python-flask-docker python3 /src/app.py
Docker Compose :
Docker compose is a tool used for creating and running multi-container applications. If you look at any typical web-application, it will have different services which may require different containers like one container for web-host, another container for database etc.
Docker-compose is installed by default if you have installed the desktop app for Docker. In other cases, it might require a seperate installation.
For docker compose, we need to create a file "docker-compose.yml".
version: "3"
services:
src:
build:
context: .
ports:
- "8000:5000"
volumes:
- ./src:/src
command: >
sh -c "python app.py"
In order to run it, we use the following command :-
% docker-compose up
Comments
Post a Comment