Предварительные требования


Прежде чем начать, убедитесь, что ваша система имеет примерно следующую конфигурацию:

  • Windows 10 Version 1803 Build 1734 и выше
  • Ubuntu for WSL 16.0.4 LTS или что-то в этом роде (ваша версия может немного отличаться)

Важно, чтобы версия и сборка Windows были не ниже того, что здесь указано. Дело в том, что, начиная с этих цифр, в ядро Windows ??WSL были внесены принципиальные изменения, которые позволяют использовать cgroups (control groups — в 2008 году добавлены в ядро Linux). А они необходимы Docker’у для управления ресурсами вашей системы в контейнерах.



Установка Docker-CE 17.09.0


Мы будем устанавливать Docker Community Edition 17.09.0 (потому что на момент написания этой статьи более свежие версии падали при установке на WSL).

Первое, что мы сделаем — избавимся от всех предыдущих установок Docker (если таковые были). Для этого запустим bash-терминал и напишем следующее:

$ sudo apt-get remove docker docker-engine docker.io containerd runc


Теперь установим репозиторий для Docker CE. Через apt-get мы можем установить нужную версию, самостоятельно не занимаясь её сборкой из исходников. Следуя рекомендациям на официальном сайте Docker, мы пишем следующие команды:

# Обновляем список пакетов
$ sudo apt-get update
# Устанавливаем необходимые пакеты, которые позволяют apt получить доступ по HTTPS
$ sudo apt-get install apt-transport-https ca-certificates curl gnupg2 software-properties-common

# Добавляем в свою систему ключ GPG официального репозитория Docker
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
#Добавляем репозиторий Docker в список пакетов:
$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

# Обновляем данные о пакетах с учетом пакетов Docker из вновь добавленного репозитория
$ sudo apt-get update

Если вы когда либо добавляли новый репозиторий с помощью apt, всё это вам в целом знакомо. Если нет — надеюсь, вы всё равно остались со мной :)

Далее устанавливаем Docker:

$ sudo apt-get install docker-ce=17.09.0~ce-0~ubuntu

Если вы не используете WSL в стиле Ubuntu, список доступных версий можно посмотреть так:

$ apt list -a docker-ce


… или использовать аналогичную команду какой-то другой библиотеки, если вы отказались от APT

В конце нужно добавить своего текущего пользователя в группу ‘docker’, чтобы получить возможность правильно использовать Docker Engine («движок»), который должен быть запущен в вашей системе с правами root.

sudo usermod -aG docker $USER

Запуск Docker на Windows


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

Чтобы немного упростить процесс, создайте в /usr /local/sbin/ новый файл — скрипт, который содержит соответствующие команды для запуска сервиса Docker:

$ sudo nano /usr/local/sbin/start_docker.sh

со следующим содержимым:

#!/usr/bin/env bash
sudo cgroups-mount
sudo service docker start

Первая команда sudo — это монтирование cgroups (оно выполнится при перезагрузке), а вторая отдает сервис docker в руки systemd (это подсистема Ubuntu для инициализации и управления службами).

Теперь разрешите скрипту запуститься и выполните его:

$ sudo chmod +x /usr/local/sbin/start_docker.sh
# Запрещаем запись
$ sudo chmod 755 /usr/local/sbin/start_docker.sh
$ /bin/sh /usr/local/sbin/start_docker.sh

Однако сервис Docker не запустится по двум причинам:

  1. Сценарий выполняет вызовы как суперпользователь, поэтому сам скрипт должен быть запущен с правами суперпользователя, чтобы работать как задумано. По идее, сделать это так же просто, как написать любую команду sudo, но для этого пользователь должен после каждой загрузки вводить свои данные, что сильно раздражает.
  2. Первая команда для монтирования cgroups должна быть выполнена в bash с повышенными привилегиями. Чтобы запустить её без ввода данных пользователем, нам придётся использовать Windows Task Scheduler.

Всё ясно? Тогда за дело…

Запуск скрипта с правами root без пользовательского ввода


В ОС семейства Linux файл /etc /sudoers определяет, кто и что может запускать с правами суперпользователя. Давайте модифицируем его так, чтобы ваш пользователь смог вызывать скрипт без необходимости постоянного ввода пароля root. (Но будьте очень осторожны с этим файлом! Очень легко выпилить себя из системы, если вы не знаете, что делаете!)

$ sudo nano /etc/sudoers

Добавим в конец файла новую строку. При этом вы должны точно знать имя своего пользователя (запустите echo $USER, если не уверены):

<your username here> ALL=(ALL:ALL) NOPASSWD: /bin/sh /usr/local/sbin/start_docker.sh

Теперь мы можем запустить сервис Docker с правами root без пользовательского ввода:

$ sudo /bin/sh /usr/local/sbin/start_docker.sh 

Ура, товарищи!

Правильный запуск Docker при загрузке Windows


Теперь при загрузке системы мы сможем запустить Docker от имени администратора с помощью отдельной команды, не требующей взаимодействия с пользователем.



Запустите Планировщик задач Windows и выберите Task Scheduler Library на левой панели. Затем выберите Create Task (создать задачу) на правой панели.



Далее вам предложат отредактировать основные настройки задачи. Дайте вашей задаче понятное название и убедитесь, что остальные настройки соответствуют моим. Важно, чтобы вы выбрали «Запуск с повышенными привилегиями» (Run with highest privileges).



Во вкладке Triggers добавьте новый триггер, который будет запускать задачу сразу же, как только локальный пользователь выполнит вход.



Переключившись на вкладку Actions, создайте новое действие, которое будет запускать bash и сразу же выполнять наш скрипт с ключом -с:

-c "sudo /bin/sh /usr/local/sbin/start_docker.sh"


Обратите внимание, что это нужно делать с повышенными привилегиями, поэтому проверьте галочку Run with highest privileges на вкладке General.



Остальные параметры в основном зависят от индивидуальных предпочтений, но я покажу свои настройки. Если хотите — можете их скопировать. Некоторые параметры питания могут не отображаться, если вы сидите на стационарной машине. Лично я пользуюсь ноутбуком.



Ну вот, всё идёт так, как мы задумали. Если вы на предыдущих этапах еще не запускали Docker, используя команды с повышенными привилегиями, просто щёлкните правой кнопкой мыши по задаче, созданной нами в Планировщике задач, и выберите «Выполнить»! Вот и всё!

Проверьте, что всё работает


Если хотите перестраховаться — перезагрузите свою машину (да, ради этого вам придётся в кое веки закрыть вкладки вашего браузера), запустите bash и введите:

$ docker run --rm hello-world

Если всё пройдёт хорошо, то вы увидите стандартное приветствие Docker’а. Сервис запустится автоматически и прямо в WSL! Мои поздравления!

Закругляемся


Вы только что установили и запустили Docker в WSL. Это означает, что ваши контейнеры теперь могут совместно использовать ??Ubuntu, уже работающую в вашей системе. Таким образом отпадает необходимость разворачивать новую (виртуализированную) ОС, как это делает обычный Docker для Windows.

Производительность работы Docker в WSL пока [на момент написания оригинальной статьи] оставляет желать лучшего, но по мере развития платформы и выпуска обновлений Windows она будет только улучшаться.

Использованные источники


  1. onomatopellan из GitHub: https://github.com/Microsoft/WSL/issues/2291#issuecomment-383698720
  2. Official Docker Documentation: https://docs.docker.com/install/linux/docker-ce/ubuntu/
  3. cgroupfs-mount: https://github.com/tianon/cgroupfs-mount
  4. Bash Command Line Interface: https://docs.microsoft.com/en-us/windows/wsl/reference