Статьи

Основы докера: практическое руководство для начинающих

В моей последней статье «Что такое Docker» я рассмотрел основы того, что такое Docker и почему вы должны его использовать. Эта статья будет первой частью серии из трех частей о том, как вы можете ее использовать.

Это руководство предназначено, чтобы быть простым, но практическим способом начать работу с основами Docker. Несмотря на то, что многое описано только в одном руководстве, оно едва затрагивает поверхность того, что может делать Docker, и силу, которую он имеет, когда дело доходит до оркестровки. В течение следующих двух недель мы проработаем еще две статьи, которые охватывают все основные части Docker, а также некоторые реальные примеры и применения.

Установка Docker

В настоящее время Docker является платформой только для Linux, что означает, что вам потребуется доступ к серверу или виртуальной машине (VM) на базе Linux. Не волнуйся; если вы не используете Linux изначально, есть ряд простых в настройке инструментов, подходящих как для Windows, так и для OS X. Самым простым из них является Boot2Docker , который поддерживает как Windows, так и OS X. Вот ссылки на инструкция по установке:

OS X также имеет Kitematic , который предоставляет оболочку GUI для многих команд, но все же позволяет вам запускать их напрямую.

Примечание. В этом руководстве предполагается, что вы установили Boot2Docker на свой локальный компьютер. Хотя почти все команды должны быть одинаковыми, в выводе журнала могут быть некоторые различия, если вы используете Docker на другой платформе.

Необходимо убедиться, что вы используете последнюю версию 1.6 (на самом деле самая последняя, ​​когда была написана эта статья — 1.6.2). Поскольку Docker быстро развивается, важно всегда быть в курсе последних событий, чтобы получить доступ к последним функциям.

После того, как вы установили Boot2Docker, вам нужно его инициализировать и запустить. Пожалуйста, ознакомьтесь с официальными установками и внимательно следите за процессом. По сути, после установки должно быть три основных шага. Вам нужно будет запустить boot2docker init, а затем boot2docker startи boot2docker shellinitнастроить и настроить среду идеально для вас.

Первые шаги

Теперь, когда у вас установлен Docker, давайте кратко рассмотрим, что доступно. Если вы пришли из мира веб-разработки, структура команд похожа на Grunt, Bower, npm и аналогичные, где каждая команда начинается с имени приложения.

Например, давайте посмотрим номера версий для установки Docker. Это также отличный способ убедиться, что Docker установлен и работает правильно. Для этого запустите:

docker version

Это должно дать вам вывод, похожий на этот:

Client version: 1.6.2 
Client API version: 1.18 
Go version (client): go1.4.2 
Git commit (client): 7c8fca2 
OS/Arch (client): darwin/amd64 
Server version: 1.6.2 
Server API version: 1.18 
Go version (server): go1.4.2 
Git commit (server): 7c8fca2 
OS/Arch (server): linux/amd64

Как вы можете видеть, я работаю с последней версией (по состоянию на май 2015 года), которая является 1.6.2.

Если вы не видите вывод, похожий на этот, это, вероятно, означает, что у вас что-то не так с вашей установкой. Убедитесь, что вы сначала запустили boot2docker init. Если это не помогло решить проблему, прочтите официальную страницу справки Docker с предложениями для получения дополнительной помощи.

Docker Images

Команда: докер тянуть

Примечание. Извлечение изображения из официального репозитория выполняется автоматически при первой попытке запуска контейнера, но это может быть удобно, если вы собираетесь работать в автономном режиме.

Команда docker pullзагрузит изображение и связанные слои из Docker Repository. Эти уровни включают в себя все, от базовой операционной системы до конечного приложения. Вы можете просматривать и искать изображения через реестр Docker , который содержит более 13 000 общедоступных изображений.

Давайте посмотрим на последнюю версию Python :

docker pull python

Затем вы должны увидеть результат, подобный следующему:

Docker автоматически вытянет различные слои для изображения Python и извлечет их. Также вы могли заметить номер версии или ее отсутствие. Поскольку мы не указали версию, Docker автоматически выбрал для нас «последнюю» версию. Версии контролируются тегами, поэтому, если мы хотим другую версию или хотим сохранить определенную версию, мы можем указать ее.

Для Python мы можем получить копию Python 2.7, выполнив:

docker pull python:2.7

2.7: Pulling from python 
1c9639a2194b: Pull complete 
80148ca1dc14: Pull complete 
034f2f72c1bf: Pull complete 
987ff7783988: Pull complete 
d833e0b23482: Already exists 
3cb35ae859e7: Already exists 
41b730702607: Already exists 
e66a33f451f4: Already exists 
05bacbdfa6eb: Already exists 
ecff3a5a9760: Already exists 
909f017029da: Already exists 
f2d8371e087a: Already exists 
python:2.7: The image you are pulling has been verified. Important: image verification is a tech preview feature and should not be relied on to provide security. 
Digest: sha256:3f57764184f783a573bd974c93f367eb2678879b1327cae3b3d1b96d5f285ca0 
Status: Downloaded newer image for python:2.7

Вы увидите, что, поскольку мы уже загрузили Python, было всего несколько слоев, которые отличались друг от друга. Время, чтобы получить эту версию также должно было быть быстрее, поэтому подход с многоуровневым изображением является большим для эффективности

Команда: изображения докера

Давайте посмотрим, какие изображения Docker у нас сейчас:

docker images

Если вы скопировали мои примеры Python выше, вы увидите вывод, подобный этому:

REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE 
python latest 1c03bc124c06 2 weeks ago 757.2 MB 
python 2.7 d833e0b23482 2 weeks ago 747.9 MB

Здесь следует отметить две важные вещи. Во-первых, он не отображает промежуточные изображения, которые образуют слои. Вы можете просмотреть их, docker images -aесли вы действительно заинтересованы, но по большей части вам не нужно беспокоиться о них.

Second, the “virtual size” appears to be nearly the same for the two, despite the fact that Docker has the intermediate images in common. This size lists the combination of all the images, but in reality the space taken on disk is significantly less.

Command:docker rmi

You can remove unused images using the rmi command. You can reference the image either by the ID or the name and also the version number. For example, let’s remove the Python 2.7 image:

docker rmi python:2.7

And the output should be similar to this:

Untagged: python:2.7 
Deleted: d833e0b2348244ed5f12b08e231ad8aa01d8e381d9746285474dfc413c79fc46 
Deleted: 987ff7783988de66ff118ca0b2a747a7884c99bbd911b0c267c308617fdf7a9b 
Deleted: 034f2f72c1bfec66d43f5fe30f85ad325e2c6eaf1caf571c4d706a14b5446ed6 
Deleted: 80148ca1dc140781b5c90a137972c1d9edc98ccaea3a1fee0b8aa37d1b28c14a 
Deleted: 1c9639a2194b30eef4a121fcc1550296b09cdfe5d6ca8790011486816eca3981

If the image is in use, Docker shouldn’t let you delete it. Still, always double check you’re removing the right image before proceeding!

Using Containers

Command:docker run

This is where the fun begins! Before we start, I just want to emphasize that containers provide process isolation, their own file system, and their own networking layer. The speed with which Docker does this is extremely fast, as you’ll see when you try it for yourself.

Let’s try by simply running Python:

docker run -t -i python

Because we’ve previously pulled down the image for the latest version of Python, it could create the container and run it nearly instantly. If it was an image which you hadn’t pulled down or used before, Docker will automatically pull down the images as part of the run command.

You should see an output like this:

Python 3.4.3 (default, Apr 30 2015, 05:46:35) 
[GCC 4.9.2] on linux 
Type "help", "copyright", "credits" or "license" for more information.
> > >

Because we ran this with the -t flag, it created a pseudo-TTY in which Python ran. This also needs the -i for interactive mode so that you can send input to the program. For those not familiar with Python, you can simply press Ctrl + D to exit. As it exits, it also shuts down the container since we had it in interactive mode.

Let’s start a basic web application as a daemon (specified with the -d flag) and have a look:

docker run -d -p 5050:5000 training/webapp python app.py

You’ll see that in this example, Docker automatically downloaded the images required to run it and then started. The output should look something like this:

latest: Pulling from training/webapp 
23f0158a1fbe: Pull complete 
0a4852b23749: Pull complete 
7d0ff9745632: Pull complete 
99b0d955e85d: Pull complete 
33e109f2ff13: Pull complete 
cc06fd877d54: Pull complete 
b1ae241d644a: Pull complete 
b37deb56df95: Pull complete 
02a8815912ca: Already exists 
e9e06b06e14c: Already exists 
a82efea989f9: Already exists 
37bea4ee0c81: Already exists 
07f8e8c5e660: Already exists 
Digest: sha256:06e9c1983bd6d5db5fba376ccd63bfa529e8d02f23d5079b8f74a616308fb11d 
Status: Downloaded newer image for training/webapp:latest 
0c8688ec4cda2d4f54abf5b5d49ff243a0bbf416dfc322b007a1f9c4f99d034d

You’ll note the large ID string at the bottom starting with 0c8688, which is the unique identifier for the container. The -p 5050:5000 maps the network port 5050 on the host to network port 5000 within the container. This is how you make the network of the container accessible to both other containers and to the world.

As this is a basic Flask web application, you should now be able to open the link in a browser. If you’re using Boot2Docker, you’ll first need to determine the IP of your Docker VM. To do this, run:

boot2docker ip

This should return a local IP which your workstation or laptop can connect to. To test the site, use the IP returned and go to http://<boot2dockerip>:5050/. It’s not much, but you should see hello world displayed to confirm it’s all working as expected.

Command:docker ps

Once we’ve created a container, we can list them all with the ps command.

docker ps

Here’s the output so far:

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 
0c8688ec4cda training/webapp:latest "python app.py" 35 minutes ago Up 35 minutes 0.0.0.0:5000->5000/tcp jovial_pasteur

We can see the information about container 0c86, including details about when it was created, the image used, network ports, and how long it’s been running.

You’ll also note that there’s only one container listed. That’s because the ps command only shows the running containers. If we want to see all of them, we can use the -a flag:

docker ps -a

You should see an output like this:

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 
0c8688ec4cda training/webapp:latest "python app.py" 35 minutes ago Up 35 minutes 0.0.0.0:5050->5000/tcp jovial_pasteur  
33b733231b4d python:latest "python3" 3 minutes ago Exited (0) 3 minutes ago condescending_nobel  
f935a7f98d00 python:latest "python3" 4 minutes ago Exited (0) 3 minutes ago elated_swartz

The other part you’ll notice is the odd name. Don’t worry, you haven’t been hacked! Docker uses a random name based on an adjective and then a famous scientist or hacker. It’s better than simply having a long ID to refer to, and we can rename this quite easily.

Command:docker rename

Let’s give our test app a better name:

docker rename jovial_pasteur conetix_test

Now if we run ps, we should see:

0c8688ec4cda training/webapp:latest "python app.py" 43 minutes ago Up 43 minutes 0.0.0.0:5050->5000/tcp conetix_test

Of course, we can specify the name at the time of creation by simply using the –name flag. For example:

docker run -d -P 5051:5000 --name app_test training/webapp python app.py

This will name the instance app_test, which is far more useful when you have more than a handful of containers.

Command:docker stop

If we no longer need our test application, we can stop it by using the docker stop command. We can either use the name or ID of the container to run the command. Here’s the command if we use the name:

docker stop conetix_test

You could also use the ID number:

docker stop 0c8688ec4cda

To confirm, Docker will echo the ID or the container name back to you as the return of the function. As in this example, the time to stop a container may seem a lot longer than the startup time. If the Docker instance doesn’t listen for a standard SIGTERM call (in order for it to cleanly shutdown), it will wait 10 seconds before calling a SIGKILL to terminate the process. As this is a basic training example, it will simply wait the 10 seconds and then kill the process.

Note: You can simply use the beginning abbreviation to refer to the container ID. Docker needs enough information to ensure the name is unique, so generally the first four characters of the ID are fine.

Command:docker start

We can of course start the container again with virtually the same syntax as stopping. You can reference the container by both the ID and the name as before.

For example:

docker start conetix_test

You’ll see a confirmation that the container started if it echoes back the container name or ID, depending on what you called to start it. You can confirm that it’s running again by using the docker ps command and/or by calling the webpage again.

Command:docker logs

  * Running on http://0.0.0.0:5050/ (Press CTRL+C to quit) 
  * Running on http://0.0.0.0:5050/ (Press CTRL+C to quit)
  * Running on http://0.0.0.0:5050/ (Press CTRL+C to quit) 
172.17.42.1 - - [21/May/2015 01:02:12] "GET / HTTP/1.1" 200 - 
172.17.42.1 - - [21/May/2015 01:02:12] "GET /favicon.ico HTTP/1.1" 404 - 
  * Running on http://0.0.0.0:5050/ (Press CTRL+C to quit) 
172.17.42.1 - - [21/May/2015 01:04:41] "GET / HTTP/1.1" 200 - 
172.17.42.1 - - [21/May/2015 01:04:41] "GET /favicon.ico HTTP/1.1" 404 -

As this is a Flask based test server, these files are straight from the Flask test webserver. You can see that it’s logged the starting of the service multiple times as the stop/start examples above were run. You can also see the calls to display the hello world page (GET /) as well as the browser seeing if the favicon existed.

For more complex systems, there are of course more complex logs. Docker 1.6 also allows you to configure centralized logging (i.e., syslog), but that’s an entire article in itself!

Conclusion

Hopefully if you’ve made it through to the end of this article, you’ve been able to follow it on your own instance of Docker and should have a better understand of how it works. The takeaway points to note are:

  • the speed of creation
  • the simplicity of the container-running environment
  • the way to access the containers

Even at this basic level, Docker offers quite a powerful system for both development and production deployment. Of course, as a basic intro, this has only just begun to scratch the surface of what’s available in Docker. We’ll be publishing further articles, which will cover the more advanced usage of Docker as well as real-world deployments and how we implemented them.

If there are any questions or parts you need assistance with, please feel free to ask in the comments below.

This article was originally published on Conetix by Tim Butler. With his kind permission, we’re sharing it here for Codeship readers.