I wrote this little article when I was learning about Docker, to use it for self reference. But then I thought that other beginners may find it useful too, so why not post it on my blog?
So let’s get right into it.
What is Docker?
If you already have an idea about what docker is, and why it’s userful, skip this part.
Docker is a platform that allows you to run your applications in an isolated environment. These isolated environments are called docker containers.
Docker containers behave like virtual machines, meaning that they run your application in a sandboxed environment, with restricted access to the host machine’s resources, but have the following differences:
- In constrast to the VMs, Docker uses the actual host machine’s kernel. For this reason Docker containers can be started in second(s) (while VMs need significantly more time to boot) and are very expendable (you can completely remove a linux debian container for example and start another in less than a second), and
- Provides all the software dependencies and tools (bins/libs) needed for your app to run, in a very cohesive way. This is means that if your app runs in a docker container, then it will run and behave the same way on every other computer/server that executes the same container via Docker.
Let’s think of a use case:
You have written a Python app, with quite a few dependencies. You have two options:
- You either ship it with a script, that installs all these the dependencies which also often require root priviledges and piss people off, or
- You ship it nicely wrapped in a container.
Now of course images need to be built somehow. The instructions to do so are placed in the Dockerfile. That’s what you ship with your app, a simple file.
Now the guy that want to run your application, will simply:
- Build the image from the Dockerfile (or pull it directly from the Docker Hub)
- And run a container from this image.
Simple as that.
Docker has way more capabilities than what we ‘ll see in this article. I will barely scratch the surface here.
Now Docker runs a daemon application in your system, supervising all your containers, and you can interact with it via its command-line interface.
In the rest of the article you’ll find the most common docker commands.
Note about the notation: all the <…> fields below are variables, used for demonstration.
||Select base image and tag to build upon (find base images at DockerHub).||FROM ubuntu:16.04|
||Runs a command on the image while building it (it is commited to the docker image). Often used to install packages.||RUN apt-get update|
||The command the container executes by default when you launch the built image. Only one CMD allowed per Dockerfile. The CMD can be overridden when starting a container with docker run $image $other_command||CMD [“/bin/bash”]|
||Exposes a port to the host machine||EXPOSE 80|
||Sets a working directory||WORKDIR /home/node|
||Sets environment variables inside the image||ENV LISTEN_PORT 8080|
||Copy files from src path (host) to destination path (inside the image) while building it||COPY config/php.ini /usr/local/etc/php|
||Specify a user for the container||USER root|
# FROM base_image:tag FROM ubuntu:16.04 # Run command inside the container RUN apt-get update RUN apt-get install -y gcc
FROM php:7.0-apache # copy files from <src dir> to <destination dir>, inside the image COPY config/php.ini /usr/local/etc/php COPY src/ /var/www/html # expose a port to the host machine EXPOSE 80
Building an Image:
docker build <directory_containing_the_dockerfile>
||Give a name to the image (tag)|
Remove an image:
docker rmi <image_ID_or_name>
List all containers (running):
List all containers (running and stopped):
docker ps -a
Create (Run) Container from an Image:
docker run [OPTIONS] <image_ID_or_name> <initial_command>
<initial_command> is the command executed on the container right after it is run, (e.g. /bin/bash), and overrides the one specified in the Dockerfile with CMD.
|Options (with example)||Explanation|
||Give a name to the container|
||Mount a volume (basically share directory with the host)|
||Maps the port of the host to the port of the container|
||Detached mode - run in the background|
||Allocates to the container a valid pseudo-tty and keeps stdin connected|
||Sets environment variable to the container|
||Always restarts the container if it stops|
||Links containers together. Docker updates the /etc/hosts file in the one container to add “another_container” as a local hostname pointing to the other container. However this method is not recommended. It is better to define a docker Network (see below).|
||Places the container in a user-defined network (see Network section below). Using user-defined networks you have an internal name resolution at your disposal. You can call other containers on the same user-defined network by name.|
There are also a lot more options, allowing you to control resource allocation to the container, networking etc. For more check this page.
docker stop <container_ID_or_name>
docker start <container_ID_or_name>
(with -a, it starts attached.)
docker rm <container_ID_or_name>
Execute a command to a running container (example):
docker exec -it <container_ID_or_name> echo "Hello from inside"
Attach local standard input, output, and error streams to a running container:
docker attach <container_ID_or_name>
If you do not see the shell, click the up arrow. To detach and leave running use CTRL+p then CTRL+q.
Create a new image from a container’s changes:
docker commit <container_ID_or_name> <new_image_name>
Create a network:
docker network create <networkname>
List available networks:
docker network ls
docker network rm <networkname>
Hope this will help you get started with Docker to “fix” the dependency hell of modern software.
For errors/suggestions, let me know asap.