Как сэкономить на покупке ноутбука: Docker Remote API via TLS +41


Совсем недавно я решился на покупку личного ноутбука. Разработка open-source проекта (приложение для Flipper) и смена места работы вынудили меня больше не использовать рабочий ноутбук для личных целей. И тут уже жалко было отдавать стоимость поддержанной Hyndai Solaris за ноутбук (на работе у меня топовая конфигурация 16" MacBook).



Поэтому решено было поумерить свой пыл и взять нищебродский самый дешевый MacBook Air 13" за 80 тысяч рублей. Однако, на mac Docker сжирает непомерное количество ресурсов, поэтому после покупки пришлось думать как же решить эту проблему. Сразу же пришла идея вынести Docker Engine куда-нибудь в онлайн. Сказано — сделано.

Настройка сервера


Установка Docker Engine на сервер


Накладные расходы docker на Linux минимальны. Docker на Mac работает на виртуальной машине Linux, когда как на Linux напрямую использует ядро хост-системы. Подробнее об этом можете почитать тут.

Так как нам важен маленький пинг, имеет смысл приобрести хостинг в Москве, но большой разницы нет.

Итого: Linux, Москва, характеристики зависят от ваших потребностей.
На ruvds.com как раз есть недорогой готовый тариф для этого. Также на ruvds.com есть возможность заказать сетап сразу с Docker CE на борту. Мелочь, а приятно.

Ищите пароль и логин в веб-интерфейсе своего хостинга и подключайтесь.



Дальше устанавливайте Docker. Отличная инструкция есть тут, ниже кратко приведу команды из неё (если у вас вдруг нет sudo, не забудьте установить его apt-get install sudo из под su):

sudo apt-get update
sudo apt-get install     apt-transport-https     ca-certificates     curl     gnupg-agent     software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo apt-key fingerprint 0EBFCD88
sudo add-apt-repository    "deb [arch=amd64] https://download.docker.com/linux/ubuntu    $(lsb_release -cs)    stable"
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io

Проверим работу docker:

docker run hello-world


Генерация ключей


Для начала нужно сгенерировать SSL ключи. Можно пойти по легкому и по сложному пути. Инструкция по сложному пути (каноническому) представлена в документации Docker. Но добрые люди запихнули все это в контейнер <10mb.

Давайте создадим для начала папки, куда будем складировать все. Папки могут быть любыми. В первой (/etc/docker/ssl) хранятся секретные ключи, во второй (~/.docker) ключи для доступа.

sudo mkdir -p /etc/docker/ssl
mkdir -p ~/.docker

Для начала создадим клиентские и CA сертификаты в локальной папке

docker run --rm -v ~/.docker:/certs     paulczar/omgwtfssl

Создадим серверные сертификаты, используя CA, сгенерированный выше. Укажите там через запятую те IP, через которые будете получать доступ к серверу. В нашем случае не забудьте указать там IP вашего сервера!

sudo cp ~/.docker/ca.pem /etc/docker/ssl/ca.pem
chown -R $USER ~/.docker
docker run --rm -v /etc/docker/ssl:/server     -v ~/.docker:/certs     -e SSL_IP=127.0.0.1,172.17.8.101,YOUR_IP     -e SSL_DNS=docker.local -e SSL_KEY=/server/key.pem     -e SSL_CERT=/server/cert.pem paulczar/omgwtfssl

Настраиваем docker daemon


Основная задача на данном этапе — пропихнуть при запуске docker аргументы командной строки с нужными нам параметрами. Как вы это сделаете не суть важно, на Ubuntu можно это сделать так:

1. Редактируем файл /etc/default/docker вашим любимым редактором

nano /etc/default/docker

И добавляем в конец переменную `DOCKER_OPTS`. Не забудьте вставить туда свой внешний IP


DOCKER_OPTS="-H=YOUR_IP:2376 -H unix:///var/run/docker.sock --tlsverify --tlscacert=/etc/docker/ssl/ca.pem --tlscert=/etc/docker/ssl/cert.pem --tlskey=/etc/docker/ssl/key.pem"

2. Добавляем аргументы на запуск сервиса. На Ubuntu файлик с параметрами запуска это /lib/systemd/system/docker.service. Добавляем строчку в подсекцию [Service]:

EnvironmentFile=/etc/default/docker

И меняем команду запуска рядышком:

ExecStart=/usr/bin/dockerd -H fd:// $DOCKER_OPTS

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

3. Перезагружаем демона

sudo systemctl daemon-reload
sudo systemctl restart docker

4. Проверьте в логах демона что все работает:

journalctl -u docker.service -f


5. Попробуем подключиться через tls:

export DOCKER_HOST=tcp://YOUR_IP:2376
export DOCKER_TLS_VERIFY=1
export DOCKER_CERT_PATH=~/.docker
docker info


Работает!

Настройка на клиенте


Прежде чем начать настраивать клиенты вам необходимо скачать папку с сертификатами на свой компьютер. Вы можете сделать это любым удобным способом. Например, через `scp`:

На удаленной машине:

mkdir /tmp/cert-for-docker && cp -v ~/.docker/{ca,cert,key}.pem /tmp/cert-for-docker

На локальной машине:

scp -r root@YOUR_IP:/tmp/cert-for-docker ~/.docker

Далее используйте эту папку для настройки клиента docker.

Mac OS CLI


Тут настройка сводится к тому что нужно прописать переменные в вашей среде и все будет работать. Однако встает вопрос: «Откуда взять голый клиент? Нам же не нужен официальный тяжеловесный клиент под 2Гб, который поставляется вместе с Docker Engine?»

Решение есть! Современный Docker уже давно поделили на клиентскую и серверную часть. Можно скачать отдельные binary клиента, собранные под macos. Официальная инструкция тут, но я приведу тут краткую выжимку:

1. Качаем последние или соответствующие вашему серверу (можно вытащить командой docker info) бинари по ссылке и распаковываем
2. Копируем бинарь в папку /usr/local/bin/ чтобы работало глобально:
sudo cp docker/docker /usr/local/bin/

3. Прописываем в ~/.bashrc или ~/.zshrc необходимые переменные окружения. Не забудьте вставить свой IP и путь к папке с сертификатам:
export DOCKER_HOST=tcp://YOUR_IP:2376
export DOCKER_CERT_PATH=PATH_TO_CERT
export DOCKER_TLS_VERIFY=1

4. Перезагружаем компьютер (шоб наверняка), проверяем:

docker info
docker run hello-world


Красота!

Jetbrains IDEs (PyCharm, IDEA, Android Studio e.t.c)


Студии Jetbrains из коробки поддерживают docker via tls. Находится эта настройка в Preference->Build, Execution, Deployment->Docker->+. Вам нужно выбрать TCP socket и ввести там свои данные. Однако есть подвох.


Если все сделать как задумано, то вылезет ошибка:
Error response from daemon: Client sent an HTTP request to an HTTPS server.
errors pretty printing info
Или
Cannot connect: Status 400: Client sent an HTTP request to an HTTPS server
Нужно явно прописывать нашей студии что протокол мы используем https:
YOUR_IP:2376
После все должно работать отлично.

Бонус (Portainer)


Чтобы эфективно отслеживать запущенные и уже отработанные контейнеры, я поставил на этот сервер Portainer. Ставится он в две строки:

docker volume create portainer_data
docker run -d -p 8000:8000 -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce

После этого на YOUR_IP:9000 будет висеть красивый веб-интерфейс и можно видеть запущенные и убитые контейнеры. Помните как мы запускали hello-world? Он тут и его можно прямо из интерфейса почистить.


Сам Portainer можно подключать к любой машине с Docker и управлять docker-контейнерами всех ваших машин из одного места. Метрика (Grafana+Prometheus+Алерты) ставиться также легко двумя командами (не забудьте установить git и docker-compose):

git clone https://github.com/stefanprodan/dockprom && cd dockprom
ADMIN_USER=admin ADMIN_PASSWORD=admin docker-compose up -d




Только вот для Storage нужно поменять sum(node_filesystem_free_bytes{fstype="aufs"}) на sum(node_filesystem_free_bytes{fstype="ext4"})



Заключение


Когда я покупал ноутбук, я не тешил себя надеждой, что мне его хватит под любые задачи, тем более что мне его хватит на Java/Android-разработку. Но я был приятно удивлен, до сих пор все мои проекты, личные и просто open-source летают в IDE. Однако я понимал, что при всей моей любви к этой пишущей машинке, Docker она не вывезет. Я был очень рад настроив один раз на удаленном сервере docker. В процессе разработки абсолютно незаметно что сервер не локальный. Ограничений каких-то не чувствую, всеравно Docker и раньше без интернета запускать было мало смысла. В общем, я очень доволен. -1 причина покупать мощный и тяжелый ноутбук.

К тому же, оверхед Docker на линукс минимальный, поэтому можно взять машину за 240 рублей в месяц у RuVDS в РФ (а со скидкой по промокоду HABR -10% и того меньше) и не беспокоиться за пинг и влияние серверных приложений на UI. Плюсом идет внешний IP (возможность показывать клиентам и держать dev-песок), приватный VPN и надежность высочайшего класса. В целом, я доволен.

Ресурсы:








К сожалению, не доступен сервер mySQL