Рабочая станция в Docker контейнере

Для чего? Мне постоянно приходят всякие идеи и некоторые из них сразу хочется попробовать, но рабочая станция не всегда под рукой, поэтому я настраивал IDE на всем что попадется под руку. В итоге устройства начали захламляться, а поддерживать и обновлять их стало тяжело. Что бы решить эту проблему я решил разместить такую «записную книжку» в облаке, и что бы ежедневно обновлялась и удаляла весь накопившийся мусор. А для работы подключаться к нему удаленно.

image

В итоге, сам того не подозревая, сделал очень удобный инструмент для решения большого количества задач: записная книжка, тестовая площадка, посмотреть то что телефон не показывает, безопасная песочница, запуск скриптов для программ работающие только GUI и мн. др. А в статье хочу поделиться методом создания таких контейнеров.
Для создания такого контейнера необходимо написать свой Dockerfile. А в статье опишу весь процесс его создания. Кто не хочет создавать сам, а хочет взять и попробовать, то внизу статьи будут ссылки на готовые образы.

Операционная система


Подойдет любой линукс. Лично я предпочитаю красивый OpenSuse, но сравнив его потребление памяти с CentOS решил выбрать последний. Ведь чем меньше памяти потребляет контейнер, тем больше можно сэкономить на его хостинге.

Начнем создавать Dockerfile:

FROM centos:7

Удаленный доступ


Для того что бы подключиться к контейнеру на нем необходимо настроить сервер удаленного доступа VNC. Для этого надо понимать два фактора:

  1. У системы нету монитора. Поэтому его придется эмулировать. Для этого существует специальный сервер x0vncserver.
  2. VNC Server должен быть не прихотлив к ресурсам. Ведь за них надо платить. А лаги в передачи сигнала должны быть минимальны, иначе они вызывают дискомфорт.


Для решения обоих проблем я выбрал TigerVNC Server для сервера и TightVNC для клиента. TigerVNC Server входит в поставку любого линукса, легкий, быстрый, а также поддерживает работу без монитора через x0vncserver. TightVNC клиент обеспечивает настолько быструю передачу картинки, что создается ощущение что это не удаленное подключение, а программа запущенная на компьютере.

Дополним Dockerfile:

FROM centos:7

RUN yum install -y epel-release dnf \
        && \
        dnf install -y \
            tigervnc-server \
        && \
        yum clean all && dnf clean all \
        && \
        rm -rf /var/cache/yum/* && rm -rf /var/cache/dnf/*


После установки программ очищаем кеш для облегчения веса образа.

Рабочий стол


Я очень люблю KDE с темой Breeze, но KDE очень прожорливый рабочий стол. Gnome и его производные оказались еще более прожорливыми. Xfce, Ice слишком уж не красивые. К счастью решение есть — рабочий стол LXQT с темой Kde-Plasma.

Доустанавливаем рабочий стол:

FROM centos:7

RUN yum install -y epel-release dnf \
        && \
        dnf install -y \
            tigervnc-server \
            openbox obconf-qt \
            lxqt-about lxqt-common lxqt-config lxqt-globalkeys lxqt-notificationd \
            lxqt-openssh-askpass lxqt-panel lxqt-policykit lxqt-qtplugin lxqt-runner \
            lxqt-session pcmanfm-qt \
            dejavu-sans-mono-fonts \
            xterm nano htop expect sudo \
        && \
        yum clean all && dnf clean all \
        && \
        rm -rf /var/cache/yum/* && rm -rf /var/cache/dnf/*


Еще чуть чуть и можно запускать.

Создание пользователя


В контейнере необходимо работать от какого то пользователя. Для этого его надо создать и задать пароль, а так же задать пароль пользователю root:

... Dockerfile

ENV HOME=/home/headless

RUN /bin/dbus-uuidgen --ensure && \
        useradd headless && \
        echo "centos" | passwd --stdin root && \
        echo "centos" | passwd --stdin headless


Здесь headless это пользователь которого мы создаем и от которого будем работать, «centos» это пароль заданный пользователю и руту. Его лучше передавать из внешних параметров при запуске контейнера, но даже в таком виде контейнер не будет уязвим, т.к. соединение будет запаролено в VNC через пароль в аргументах.

Настройка запуска vnc сервера


Для запуска понадобиться вспомогательный скрипт который настроит наш VNC Server:

#!/usr/bin/expec

spawn /usr/bin/vncserver :1 -fg -geometry 1820x960
expect "Password:"
send "$env(password)\r"
expect "Verify:"
send "$env(password)\r"
expect "Would you like to enter a view-only password (y/n)?"
send "n\r"

set timeout -1
expect eof


Его необходимо положить рядом с Dockefile, позже он будет включен в контейнер и с него будет начинаться запуск программы. В этом файле обязательно необходимо указать разрешение в котором вы планируете работать, например у меня задано 1820×960. Если указать меньше чем размер клиентского окна, то сервер может вылететь из-за нехватки памяти. Если указать больше, то картинку надо будет масштабировать и элементы рабочего стола станут слишком маленькими. Так же в этом скрипте будет задан пароль из переменных, которые будут переданы в параметрах запуска контейнера.

Осталось скопировать этот файл в контейнер и дописать параметры его запуска:

... Dockerfile

COPY ./startup.sh ${HOME}
RUN mkdir -p ${HOME}/.vnc \
        && \
        echo '#!/bin/sh' > ${HOME}/.vnc/xstartup && \
        echo 'exec startlxqt' >> ${HOME}/.vnc/xstartup && \
        chmod 775 ${HOME}/.vnc/xstartup \
        && \
        chown headless:headless -R ${HOME}


WORKDIR ${HOME}
USER headless
ENTRYPOINT ["expect", "./startup.sh"]

Вообщем то и все, можно запускать. Если запутались в составлении Dockerfile, то его полную версию можно найти у меня в репозитории, а готовый контейнер в docker hub.

Для запуска готового контейнера необходимо выполнить команду

docker run -it --rm -e password='YOUR_VNC_PASSWORD' -p5901:5901 labeg/centos-lxqt-vnc


И подключиться используя клиент TightVNC.
image

После подключения необходимо ввести пароль от пользователя заданный ранее. Так же рекомендуется сразу же его сменить для большей безопасности.
Для включения красивого оформления как в скриншоте выше необходимо зайти в Пуск > Preferences > Appearance > LXQt Theme и выбрать тему Kde-plasma.

Программы для работы


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

FROM labeg/centos-lxqt-vnc:latest

USER root

# dotnet vscode monodevelop nodejs git2
RUN rpm -Uvh https://packages.microsoft.com/config/rhel/7/packages-microsoft-prod.rpm \
        && \
        rpm --import https://packages.microsoft.com/keys/microsoft.asc && \
        sh -c 'echo -e "[code]\nname=Visual Studio Code\nbaseurl=https://packages.microsoft.com/yumrepos/vscode\nenabled=1\ngpgcheck=1\ngpgkey=https://packages.microsoft.com/keys/microsoft.asc" > /etc/yum.repos.d/vscode.repo' \
        && \
        rpm --import "http://keyserver.ubuntu.com/pks/lookup?op=get&search=0x3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF" && \
        su -c 'curl https://download.mono-project.com/repo/centos7-vs.repo | tee /etc/yum.repos.d/mono-centos7-vs.repo' \
        && \
        yum install -y https://centos7.iuscommunity.org/ius-release.rpm \
        && \
        curl -sL https://rpm.nodesource.com/setup_13.x | bash - \
        && \
        dnf install -y geany git2u git2u-gui code monodevelop firefox dotnet-sdk-3.1 nodejs gnome-terminal gnome-system-monitor \
        && \
        npm install -g gulp typescript npm-check-updates \
        && \
        chown headless:headless -R ${HOME}

USER headless

RUN code --install-extension ms-vscode.vscode-typescript-tslint-plugin && \
    code --install-extension dbaeumer.vscode-eslint && \
    code --install-extension mrmlnc.vscode-scss && \
    code --install-extension visualstudioexptteam.vscodeintellicode && \
    code --install-extension ms-dotnettools.csharp && \
    code --install-extension joelday.docthis && \
    code --install-extension mrmlnc.vscode-remark && \
    code --install-extension eamodio.gitlens


В скрипте устанавливаются инструменты для Typescript и C# разработки под линуксом. Это NodeJS, VS Code с необходимым расширениями и Monodevelop (он же Visual Studio for Mac).

Запускается так же просто как и предыдущий образ

docker run -it --rm -e password='YOUR_VNC_PASSWORD' -p5901:5901 labeg/devpc


Теперь в считанные секунды можно разворачивать чистое рабочее окружение.
image

Репозитории и готовые образы


Если вам нужны готовые репозитории и образы или вы хотите улучшить имеющиеся, например через параметры запуска задать пароль пользователя, разрешения экрана, или сделать рестарт VNC сервера после его падения, то добро пожаловать в мои репозитории.
Базовый образ с рабочим столом GihubDockerhub
Образ с инструментами Typescript и C# Gihub Dockerhub

© Habrahabr.ru