Docker Basics
Introduction
Docker has loads of commands, im not aiming to cover all of them instead to provide a narrative that makes it easier to get up to speed with docker.
- There are images and containers.
- Images are pretty much like a virtual computer image.
- Containers are running images.
Images
You can download prebuilt images from Docker Hub that contains some OS and some programs installed onto it.
First you have to download an image.
You can do this with the pull command.
1 | docker pull <dockerhub user>/<image> |
This downloads the crossbar latest image onto your computer.
The location of the images is in /var/lib/docker but there is some magic involved.
The images are stored in /var/lib/docker/graph/
Note that images are just diffs from the parent image. The parent ID is stored with the image’s metadata /var/lib/docker/graph/
You can check all your downloaded images:1
docker images
You can remove an image:
1 | docker rmi <id> |
If you delete it gets deleted from your computer.
You cant delete an image if you have a running container that uses it.
Dockerfiles
A dockerfile is a file that describes an Image.
A docker file can be built on top of an existing image.
In this way you can tweak and add additional functionality to an existing Image.
You can create an image from a Dockerfile with the build command:
1 | docker build -t <image-name> <path-to-dockerfile> |
If you specify a name its easier to reference during the container creation.
If you dont set a name you can reference an image by id or the auto generated name.
Dockerfiles has their own syntax but its mostly bash commands with some directive commands.The most important command is the ENTRYPOINT which gets run each time when the container starts.
Containers
Containers are instantiated images.
Containers are either running or stopped.
You can list you running containers:
1 | docker ps |
You can list all your containers, this shows stopped containers too:
1 | docker ps –a |
You can stop a container:
1 | docker stop <name> |
You can start or restart a container:
1 | docker start <name> |
You can check the output of the docker container:
1 | # snapshot |
Containers from Images - docker run
Docker run is basically a combination of two commands.
Docker create and docker start.
So if you call run on an image it first creates a container from that image then starts that container.
You can run a container from an image:
1 | docker run <dockerhub username>/<image> |
This downloads the image if its not present on the computer then start up a virtual machine based on the image.
If you already have the image stored on your computer you can reference it by its name or id:
1 | docker run <image> |
To see the output of the running container you have to specify the -i -t flags:
1 | docker run -it <image> |
To detach from a running container use the -d flag.
1 | docker run -d <image> |
To see the output of an already stopped or crashed container:
1 | docker logs <container name> |
To delete the container after we stop it (Useful when creating and debugging images) use the –rm flag:
1 | docker run -it --rm <image> |
Settings with docker run
These can be set either from the Dockerfile or from directly the docker run command.
To open a port on container use the –expose or -e flag:1
2# Expose the port 1337 on the container
docker run -it -e 1337 <image>
If a port is exposed it does not mean its mapped to the host.
You can map an exposed port on the container to a host port with the -p flag.
1 | docker run -e <container port> -p <host port>:<container port> <image> |
You can map folders on the host into the container with –volume or -v:
1 | docker run --volume <path to host folder>:<path to container folder> <image> |
Processes with docker run
Most of the images define some sort of main process as the default command.
By default a container is stopped when the main process is finished.
The main process can be defined in the Dockerfile as an Entrypoint or CMD but you can overwrite it trough docker run.
1 | docker run –it –rm ubuntu bash –c "sleep 5; echo all done" |
Here the container waits 5 seconds then prints a message and exits.
We can extend the lifetime of the container if we detach it with the -d flag.
In this form the container will keep running in the background even after the main process is finished.
1 | docker run –it –d ubuntu bash |
To enter a container running in the background you can use the attach command.
1 | docker attach <container name> |
Stepping into a Container - docker exec
You can do multiple things with exec. You can run commands and create new processes from the host in the container. The coolest example of that is where you enter the containers shell.
You can “step into” the container shell by specifying the shell in the container.
Note that all containers should have sh but some of them has /bin/bash as well. This depends on the image you are using. What happens is you create a new process in the container and attach to it.
1 | docker exec <container name> sh |
Images from containers - docker commit
Lets say we have a container that we stepped into with exec and did some changes.
In order to save those changes we can save the container to an image.
This can be alternative to creating a Dockerfile, you run your base image do some changes interactively then commit the container into an image.
1 | docker commit <container name> -t <image name> |
Multiple Containers - docker compose
If you have multiple images and containers you want to manage together you can use docker compose to do that.
In a docker-compose.yml file you specify the path to each containers Dockerfile and the settings you want to start with.
Then you start or stop all containers with a single command:
1 | docker compose up |
Remote hosts - docker machine
With docker machine you can mount a remote computer and manage the containers running remotely just like you would on your local computer. With the combination of docker compose and docker machine you can control microservices on a remote host like AWS from your local terminal.
Multiple Hosts - docker swarm
It turns a pool of Docker hosts into a single, virtual host using an API proxy system. It has load balancing capabilities as well.
Workflow - Using an existing image
- Download the image
- Run the image
Workflow - Dockerizing your app
- First you create your app
- Find a docker image that has what you need
- Create a Dockerfile that builds on that image
- Test your container (ideally with docker run –rm)
- Create a Dockerfile for each of your services.
- Create a docker compose file
- Mount your remote machine with docker machine
- Start / Stop your services with docker compose