Learning Docker - running Docker commands

When I started to learn Docker I made a mistake and instead of learning basic commands, I jumped into Docker Compose. I was so eager to use it that I missed all what's important. So I took a step back and forced myself into command line interface. After many images I created and lot of container I was experimenting with I finally got it.

Before we start to run Docker commands we need to know what are images and containers. The former is a blueprint we will be using to create containers. Images are stateless and immutable. Container is an instance of image we can interact with, save and restore its state. In words of object oriented programming - image is a class and container is an object created from that class.

docker run

It's time to run our first Docker command. Let's start with run.

docker run -e MYSQL_ROOT_PASSWORD=root mysql

So what happened here? Docker run command will execute two other commands - create and start. It takes source image (in this case mysql), creates local image and starts it with environment variable MYSQL_ROOT_PASSWORD set to root. If we run this command we'll see a lot of output. This is MySQL starting up. After few seconds we will be able to use this container.

If we want to run our container in background we should detach it. We can do it with -d option.

docker run -d -e MYSQL_ROOT_PASSWORD=root mysql

As I mentioned before MYSQL_ROOT_PASSWORD is an environment variable we are setting with -e option. List of all environment variables we can set is usually available in image documentation (we'll get to it).

Persisting data

We shouldn't put any data in containers. Container can be stopped, destroyed, updated and our data will be lost. There's much better way to handle data - volumes. If we want our MySQL database to persist data, we can do something like this.

docker run -d -v /local/dir/for/storing/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root mysql

Restart policy

Our container isn't immortal. There is a lot of ways it can be stopped. If we don't mind we can restart it manually. But if we want to automate this, we should use --restart flag. It accepts one of four different values. I use always. This means that if my container will be stopped (excluding docker stop command) it will be restarted.

docker run -d -v /local/dir/for/storing/data:/var/lib/mysql --restart=always -e MYSQL_ROOT_PASSWORD=root mysql

Publishing ports

With run command we are able to publish ports exposed by our container. Why do we want to do this? Well, two most common use cases are: host machine already uses given port or we want to run multiple containers that expose the same port.

docker run -d -v /local/dir/for/storing/data:/var/lib/mysql --restart=always -p 3307:3306 -e MYSQL_ROOT_PASSWORD=root mysql

By default MySQL image exposes 3306 port. Using -p option we can publish this port to the host. In above example host can access mysql server on 3307 port.

Naming our container

Another thing we will do with run command it naming our container. It's not important, it's not even necessary but it will helps us identify containers we have spawned. It's helpful if we are running multiple versions of one image (in our example MySQL server). If we don't define a name it will be generated randomly.

docker run -d -v /local/dir/for/storing/data:/var/lib/mysql --restart=always -p 3307:3306 --name=local_mysql -e MYSQL_ROOT_PASSWORD=root mysql

Stopping and starting containers

If for some reason we want to stop out container (for example we want to test how our app will handle database connection issue) we can use docker stop command followed by a name of the container we want to stop. If we didn't assign any name, we need to check it with docker ps command.

docker stop local_mysql

Guess what's the name of the command we can use to start container.

docker start local_mysql

Executing commands

Last Docker command we learn today will be exec. It allows to run specified command inside Docker container. Let's try to run mysql command inside our local_mysql container.

docker exec -it local_mysql mysql -P 3307 -u root -p

Options -i and -t (here combined to -it) are responsible for making our console interactive. In other words thanks to them we are able to interact with container's standard input and output. Because we switched port we need to specify it in mysql command with -P option.

Where can I find Docker images?

If we want do use existing images we need to know where to find them. The best source of Docker images is Docker Hub. We can search for almost anything and use it as base image for our containers. Each image (at least official ones) have detailed description with all environment variables we can set, volume paths and version number. If we look at MySQL image we will see numerous versions we can use. In this case we can use versions from 5.5 up to 8. We can specify major, minor or latest version. How can we do this. It's pretty simple. Remember docker run command? Last part of that command is an image name. We can add specified version (tag) to it: mysql:5.6. So the entire run command will look like this.

docker run -d -v /local/dir/for/storing/data:/var/lib/mysql --restart=always -p 3307:3306 -e MYSQL_ROOT_PASSWORD=root mysql:5.6

Summary

In today's post we learned few important Docker commands. These commands will allow us to enjoy predefined images. But what if we want to use customised image? We'll cover this in next post. I'll give you a hint -we'll use Dockerfile for that.

Useful links