(Go) The Ultimate Guide to Docker

Docker is a relatively new and very fast growing project for creating very lightweight "virtual machines". Note that the quotation marks here are very important, Docker is not creating a real virtual machine, but more like a chroot with hormones, well, a lot of hormones.

Before we go any further, let me say that as of now (January 4th, 2015), Docker only works on Linux , not Windows or OSX. I'll talk about Docker's architecture later, and you'll see why. So, if you want to use Docker on a non-Linux platform, you need to run Linux in a virtual machine.


This tutorial has three goals: explain the problem Docker solves, explain how it solves the problem, and explain what techniques it uses to solve the problem. This is not a tutorial to teach you how to run and install Docker, there are many such tutorials on Docker , including online interactive tutorials by Docker authors . There is a step-by-step description at the end of the article, which aims to tie together all the theories in the article with a clear real-world example, but without going into too much detail.

 

What can Docker do?

Docker can solve problems that virtual machines can solve, but also solve problems that virtual machines cannot solve due to excessive resource requirements. Things that Docker can handle include:

  • Isolate application dependencies
  • Create an application image and copy it
  • Create out-of-the-box applications that are easy to distribute
  • Allows instances to scale easily and quickly
  • Test apps and destroy them later

The idea behind Docker is to create portable, lightweight containers for software programs that can run on any machine with Docker installed, regardless of the underlying operating system, similar to the containers used by ships, and they succeeded!

 

What exactly does Docker do?

In this section I won't explain what technologies Docker uses to do its work, or what specific commands are available, these are placed in the last section, and here I will explain the resources and abstractions that Docker provides.

The two most important concepts of Docker are images and containers. In addition to this, links and data volumes are also important. Let's start with mirroring.

 

mirror

Docker images are similar to virtual machine snapshots, but are lighter, very, very lightweight (more on that in the next section).

There are several ways to create a Docker image, most of which are to create a new image based on an existing image, since there are public images for almost anything you need, including all major Linux distributions, you should not find what you need mirror image. However, even if you want to build an image from scratch , there are several ways .

To create an image, you take an existing image and modify it to create a subimage of it. There are two ways to do this: by specifying a base image and the modifications that need to be done in a file; or by "running" an image, modifying it and committing it. Each approach has its own advantages, but the first file approach is generally used to specify changes.

An image has a unique ID, and a human-readable name and tag pair. Mirrors can be named like ubuntu:latest, ubuntu:precise, django:1.6, django:1.7, etc.

 

container

Now for the container. You can create a container from an image, which is equivalent to creating a virtual machine from a snapshot, but more lightweight. Applications are run by containers.

For example, you can download an Ubuntu image (there is a public repository of images called docker registry ), make a few modifications: install Gunicorn and your Django application and its dependencies; then create a container from that image and start it after running your app.



 Containers, like virtual machines, are isolated (with one caveat, which I'll discuss later). They also have a unique ID and unique human-readable name. It is necessary for containers to expose services to the outside world, so Docker allows specific ports of containers to be exposed.



 

There are two main differences between containers and virtual machines. The first is: they are designed to run a single process and don't emulate a full environment well (look at LXC if that's what you need ). You might try running an instance of runit or supervisord to start multiple processes, but (in my humble opinion) it's really not necessary .

The single-process vs. multi-process battle is very exciting . What you should know is that the Docker designers strongly advocate the "one process per container approach", and if you're going to choose to run multiple processes in a container, the only case is: for debugging purposes, run something like ssh to access A running container, but the docker exec command solves the problem.

The second big difference between containers and virtual machines is: when you stop a virtual machine, no files are deleted except maybe some temporary files; when you stop a Docker container, the initial state (the state of the image used to create the container) ) will be lost. This is one of the biggest mindset changes you have to make when using Docker: Containers are ephemeral and disposable .

 

data volume

If your e-commerce site just received 30k from a customer, the kernel crashes, and all database changes are lost...not a good thing for you or Docker, but don't worry. Docker allows you to define data volumes - the space used to hold persistent data. Docker forces you to define the application part and the data part, and requires you to separate them.

Volumes are container-specific, you can use the same image to create multiple containers and define different volumes. Volumes are stored on the host filesystem where Docker is running. You can specify the directory where the volumes are stored, or let Docker store them in the default location. Nothing saved on any other type of filesystem is a volume, more on that later.



 

Link

Links are another important part of Docker.

When a container is started, it will be assigned a random private IP, and other containers can use this IP address to communicate with it. This is important for two reasons: first, it provides a channel for the containers to communicate with each other, and second, the containers will share a local network. I once had an issue where I started two elasticsearch containers for two clients on the same machine, but left the cluster name as default, and the two elasticsearch servers immediately became an autonomous cluster.

To enable inter-container communication, Docker allows you to reference other existing containers when you create a new container. The referenced container in the container you just created will get an alias (that you specify). Let's just say, the two containers are linked together.

So if the DB container is already running, I can create the web server container and reference this DB container at creation time, giving it an alias like dbapp. In this newly created web server container, I can communicate with the DB container at any time using the hostname dbapp.

Docker goes a step further and requires you to declare which ports a container should open to other containers when it is linked, otherwise there will be no ports available.



 

Portability of Docker images

There is one thing to keep in mind when creating images. Docker allows you to specify volumes and ports in an image. Containers created from this image inherit these settings. However, Docker doesn't allow you to specify anything non-portable on the image.

For example, you can define volumes in images as long as they are stored in the default location used by Docker. This is because if you specify a specific directory in the host filesystem to hold the volume, other hosts using the image cannot guarantee that the directory exists.

You can define which ports to expose, but only those that are exposed to other containers when the link is created, you cannot specify which ports are exposed to the host because you have no way of knowing what ports are available to the host using that image.

You also cannot define links on mirrors. Using links requires referring to other containers by name, but you can't predict how each host using that image will name the container.

Images must be fully portable, Docker does not allow exceptions.

That's all for the main part, creating images, creating containers with them, exposing ports and creating volumes when needed, connecting several containers together via links. But how can this be achieved without incurring additional overhead?



 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326430967&siteId=291194637