Docker quick reference
The only containerization technology you need
- Docker is based on LXC, an operating system level containerization method. Docker offers a high level tool on top of that.
- The main purpose of Docker is to package and containerize applications with their dependencies and ship them
- Docker uses Namespaces to provide isolation
- Docker uses
cgroups
(control groups) to restrict the amount of hardware resources allocated to each container
- Docker uses
Common Docker commands
-
docker run
- Run a container from an image. If the image is not present on the host, docker will search and download it from the configured registry (DockerHub)
- Attached or Detached mode
docker run -d image_name
-
docker attach container_id
: Attach a detached container
- Specify a tag
-
docker run -d redis:4.0
: Here,4.0
is the tag - If you don't specify a tag,
latest
is considered by default
-
-
docker ps
- List running containers with some basic information
-
docker ps -a
: List ALL containers
-
docker stop container_name_or_id
- Stop a running container
-
docker rm container_name_or_id
- Remove a stopped container
-
docker images
- Show available images
-
docker rmi image_name
- Remove an image
-
docker pull
- Only pull an image but don't run
- Execute a command on a running container
docker exec container_name_or_id cat /etc/hosts
- Port mapping : map a port from inside the docker container to the host its running on
docker run -p 80:5000 tanmay/my-simple-app
- The above command will make sure that all traffic on port 80 of your host is routed to port 5000 inside your docker container
- Data persistance
- You can map a directory on your host (outside the docker container) to a file system location of your container to make sure the data persists
- e.g. Assume that you're running a mysql container
- the mysql server stores its data at the location
var/lib/mysql
. If you remove the container, this data will be lost - you can map a directory on your host instead like so:
docker run -v /opt/datadir:/var/lib/mysql mysql
- This way when the container runs, it will mount the external directory and store the data there
- the mysql server stores its data at the location
- Inspecting the container (sometimes
ps
is not enough)docker inspect container_name_or_id
- Returns the container configuration in JSON format
- Logs
docker logs container_name_of_id
- Passing environment variables to
docker run
docker run -e APP_COLOR=blue simple-web-app
- List all networks
docker network ls
Important points
- A container lives only until the process inside it is alive
- To map the standard input of your host to a container, you need to pass the
i
flag for the interactive modedocker run -i redis
- To get the app's output on your terminal, use the
-t
flag for the terminal modedocker run -it redis
- The
-it
combination makes sure that your container is attached to the terminal as well as running in interactive mode
Dockerfile
- All Dockerfiles must start with the FROM command (every Docker image derives from a base image. Either an OS or an existing app)
- Each line in the Dockerfile creates a new layer
- All built layers are cached. This allows rebuilds to be fast
- Instructions
- CMD
- Defines the program that will be run within the container when it starts
- The command and its parameters should be separately specified like so :
CMD ["sleep", "5"]
and NOT likeCMD ["sleep 5"]
- You can also specify the command to be run at startup from the command line:
docker run ubuntu sleep 10
. This will override the command in the Dockerfile
- ENTRYPOINT
- This instruction will append to the list of existing commands in the Dockerfile
- CMD
from IPython.display import Image
Image("../images/entrypoint_and_cmd.png")
Image("../images/entrypoint_and_cmd_2.png")
Networking in Docker
- When you install docker, it creates 3 networks automatically:
- Bridge: this is the default network a container gets attached to
- it's a private and internal network
- All containers attched to Bridge get an internal IP address by default
- The containers can access each others using this IP if required
- none
- the containers are not attached with any network. They are completely isolated.
- host
- if you use the
host
network, you can directly run a container on the required port, without any port mapping - but this also means that you won't be able to run multiple instances on the same host on the same port
- if you use the
- Bridge: this is the default network a container gets attached to
- You can modify the network information using the cli parameter
--network
docker run ubuntu --network=host
- Create a network
docker network create --driver bridge --subnet 182.18.0.0/16 my-custom-network
- Containers can reach each others using their names
- Docker has a built in DNS server and it always runs at
127.0.0.11
- Docker has a built in DNS server and it always runs at
Storage in Docker
-
When you install docker, it creates the following directory structure
- /var/lib/docker
- aufs
- containers
- image
- volumes
- /var/lib/docker
-
Adding a persistent volume to a container
-
docker volume create data_volume
(this gets stored in thevolumes
directory above) docker run -v data_volume:/var/lib/mysql mysql
- If you run the above command w/o first creating a volume, docker will automatically create a volume
docker run -v data_volume2:/var/lib/mysql mysql
- If you want to mount an existing location on the host, use the following command instead (This is called a
Bind
mount)docker run -v /data/mysql:/var/lib/mysql mysql
- The more recent syntax is as follows:
docker run --mount type=bind,source=/data/mysql,target=/var/lib/mysql mysql
-
-
Docker uses readily available storage drivers on the OS to handle all this
- AUFS
- ZFS
- BTRFS
- Device Mapper
- Overlay
- Overlay2
Example - a simple web app with UI
Assume that the app is using several different services
- A python app called
voting-app
that has a front end UI - A redis in memory database
- A postgreSQL database
- A worker written in .NET
- A result app that shows the votes
How will this look using plain docker commands?
Note: The following way of Linking together containers is soon going to be deprecated, and will be replaced with better methods. Showing them here just for knowledge.
- docker run -d --name=redis redis
- docker run -d --name=db postgres:9.4
- docker run -d --name=vote -p 5000:80 --link redis:redis voting-app
- docker run -d --name=result -p 5001:80 --link db:db result-app
- docker run -d --name=worker --link db:db --link redis:redis worker
Using Docker compose (Version 1)
redis:
image: redis
db:
image: postgres:9.4
vote:
image: voting-app
ports:
- 5000:80
links:
- redis
result:
image: result-app
ports:
- 5001:80
links:
- db
worker:
image: worker
links:
- redis
- db
Now, use docker-compose up
to create the entire stack