Запуск графических приложений в Docker

от автора

Введение.

В основном, Docker привыкли использовать для запуска сервисов или процессов не предполагающих визуальной составляющей. Однако могут быть ситуации, когда в контейнере возникает необходимость открыть среду разработки и на месте продебажить один сервис или два сервиса, каждый в своем контейнере. В прошлой статье я писал, как запускать графические приложения в wsl, в текущей расскажу, как можно запустить разными способами в контейнере qtcreator. Аналогично можно будет поступить с любой средой разработки или программой.

Подготовка.

Включаем wsl на windows, если он отключен, говорим ему работать в режиме wsl2 – ровно так как описано в документации Майкрософт.  Устанавливаем Docker.
Создаем для примера контейнер simpleimg_0 на основе ubuntu:18.04 и тут же запускаем его в интерактивном режиме:

docker run --name simpleimg_0 -it ubuntu:18.04 /bin/bash

Поставим mc по желанию для своего удобства:

apt update && apt install mc

Согласимся доставить все зависимости и получим:

Установка qtcreator.

Теперь устанавливаем qtcreator:

apt install qtcreator

Соглашаемся добавить 1,6гб зависимостей:

При попытке запуска видим, что ничего не получиться. Теперь решим этот вопрос.

Запуск qtcreator.

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

На следующей оставляем все по умолчанию:

На последней снимаем средний флажок и устанавливаем последний:

Теперь видим значек х-сервера в трее около часов.

Теперь нам нужно узнать заветный адрес х-сервера, который нужно нам указать в контейнере. Для этого открываем консоль на хостовой ОС и запрашиваем информацию по сети:

ipconfig

Находим в выводе информацию по сети wsl:

Берем этот адрес и вносим его в переменную окружения DISPLAY в ОС контейнера, вспомнив про номер дисплея:

export DISPLAY=172.30.144.1:0

Повторно запускаем qtcreator и ура, он запускается в окне на заднем плане за консолью:

Заходим в настройки, проверяем, что компиляторы уже стоят:

Есть дебаггер, но нет Cmake и нет комплекта Qt.

Закрываем окно программы, переходим в консоль и доставляем Cmake:

apt install cmake

Проверяем и видим, что при следующем запуске Cmake уже подтянулся в настройках:

Любые зависимости таким образом можно самостоятельно доставить.

Посмотрим сколько весит наш контейнер для отладки – не очень то и много, т.к в несколько раз меньше чем виртуальная машина на основе убунты:

После того как мы завершили работу с контейнером, то запустить его снова в интерактивном режиме можно командой:

docker container start simpleimg_0 –i

Dockerfile, автоматизация.

Все то, что мы выше проделали руками, можно прописать в Dockerfile и создать все одной командой из консоли.

Qt в dockerfile можно установить несколькими способами – через apt install, через python утилиту aqt, через офиц. установщики qt.

Первый способ в ручном режиме разобрали в первой части статьи, предлагаю ниже разобрать установку через python. Создаем Dockerfile со следующим содержимым и переходим в консоли к нему на один уровень:

FROM ubuntu:18.04  RUN apt-get -y update && DEBIAN_FRONTEND=noninteractive apt-get -y install \     git \     cmake \     python3 \     python3-pip \     build-essential \     libdbus-1-3 \     libpulse-mainloop-glib0  RUN pip3 install aqtinstall  ARG QT=5.11.0 ARG QT_TOOLS=tools_qtcreator ARG QT_HOST=linux ARG QT_TARGET=desktop ARG QT_ARCH=gcc_64 RUN aqt install-qt --outputdir /opt/qt ${QT_HOST} ${QT_TARGET} ${QT} ${QT_ARCH} RUN aqt install-tool -O /opt/qtcreator ${QT_HOST} ${QT_TARGET} ${QT_TOOLS}  ENV PATH /opt/qt/${QT}/gcc_64/bin:/opt/qtcreator/Tools/QtCreator/bin:$PATH ENV QT_PLUGIN_PATH /opt/qt/${QT}/gcc_64/plugins/ ENV QML_IMPORT_PATH /opt/qt/${QT}/gcc_64/qml/ ENV QML2_IMPORT_PATH /opt/qt/${QT}/gcc_64/qml/ 

Здесь мы сначала ставить необходимые зависимости для сборки, после этого ставим утилиту aqtinstall и выполняем ей две команды:
aqt install-qt – устанавливает библиотеки qt
aqt install-tool – устанавливает qtcreator.

Теперь создаем образ из этого файла:

docker build -f Dockerfile -t simpleimg_qtcr .

Запускаем, и вспоминаем, что нужно прописать актуальный адрес DISPLAY.

Минус этого способа – долгая установка, т.к все стягивается с офис.репозитория Qt. Документация для утилиты aqt.

Разберем еще один способ, лишенного этого недостатка – установка с использованием оффлайн-установщика с офиц. сайта. Качаем с офиц. репозитория установщик. Качаем скрипт не интерактивного установщика qt-installer-noninteractive.qs. Открываем последний скрипт в редакторе и кое-что правим.
Вписываем данные авторизации:

Controller.prototype.CredentialsPageCallback = function() {   var page = gui.pageWidgetByObjectName("CredentialsPage");   page.loginWidget.EmailLineEdit.setText("email");   page.loginWidget.PasswordLineEdit.setText("pass");   gui.clickButton(buttons.NextButton); }

Вписываем куда установить фреймворк:

Controller.prototype.TargetDirectoryPageCallback = function() {     //dev is the user in our docker image     gui.currentPageWidget().TargetDirectoryLineEdit.setText(installer.value("/opt/Qt5.11.0"));     gui.clickButton(buttons.NextButton); }

В разделе Controller.prototype.ComponentSelectionPageCallback = function() указываем какие компоненты установить, а какие нет:

widget.deselectAll();     widget.selectComponent("qt.tools.qtcreator");     widget.selectComponent("qt.qt5.5110");     widget.selectComponent("qt.qt5.5110.gcc_64");          widget.deselectComponent("qt.qt5.5110.android_x86");     widget.deselectComponent("qt.qt5.5110.android_armv7");     widget.deselectComponent("qt.qt5.5110.android_armv7");     widget.deselectComponent("qt.qt5.5110.doc");     widget.deselectComponent("qt.qt5.5110.examples");     widget.deselectComponent("qt.qt5.5110.src");

На одном уровне с установщиком создаем dockerfile:

# run as: # docker build -t offline_qtcr -f Dockerfile path_to_distrib FROM ubuntu:18.04 MAINTAINER Chesnochenko <ss@ss.org>  ARG DEBIAN_FRONTEND=noninteractive RUN apt update && \     apt -o Dpkg::Options::="--force-confold" install -q -y mc build-essential \     mesa-common-dev libglu1-mesa-dev libdbus-1-dev x11-xkb-utils sudo curl \     libfontconfig1 libxrender1 libxi6 libgconf-2-4 libxcb-xinerama0 gdb cmake && \     apt clean && rm -rf /var/lib/apt/lists/*  RUN useradd -G users,video -ms /bin/bash user && \ echo 'user:12345678' | chpasswd -e && \ echo 'user ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers && \ mkdir /run/user && \     chown user:user /run/user && \ apt update && apt install -y locales language-pack-ru libfontconfig1 && \     update-locale LANG=ru_RU.UTF-8 && \ echo 'LANG=ru_RU.UTF-8' >> /etc/default/locale && \ echo 'export LC_ALL=ru_RU.UTF-8' >> /home/user/.bashrc && \ echo 'export LANG=ru_RU.UTF-8' >> /home/user/.bashrc && \ locale-gen ru_RU.UTF-8 && \ apt install -y --reinstall locales && \ apt clean && rm -rf /var/lib/apt/lists/*   WORKDIR /tmp/ COPY qt-opensource-linux-x64-5.11.0.run . COPY qt-installer-noninteractive.qs . RUN chmod a+x qt-opensource-linux-x64-5.11.0.run \     && chmod a+x qt-installer-noninteractive.qs   RUN curl https://www.openssl.org/source/openssl-1.0.2l.tar.gz | tar xz && cd openssl-1.0.2l && \     ./config && make -j $(nproc) && make install && \     ln -sf /usr/local/ssl/bin/openssl `which openssl`  RUN ./qt-opensource-linux-x64-5.11.0.run -platform minimal --verbose --script ./qt-installer-noninteractive.qs RUN rm -f qt-opensource-linux-x64-5.11.0.run qt-installer-noninteractive.qs  ENV DISPLAY=172.30.144.1:0 RUN echo 'export DISPLAY=172.30.144.1:0' >> /home/user/.bashrc #RUN setxkbmap -model pc105 -layout us,ru -option grp:alt_shift_toggle   ARG QT=5.11.0 ARG QT_HOST=linux ARG QT_TARGET=desktop ARG QT_ARCH=gcc_64 ENV PATH /opt/Qt${QT}/${QT}/gcc_64/bin:/opt/Qt${QT}/Tools/QtCreator/bin/:$PATH ENV QT_PLUGIN_PATH /opt/Qt${QT}/${QT}/gcc_64/plugins/ ENV QML_IMPORT_PATH /opt/Qt${QT}/${QT}/gcc_64/qml/ ENV QML2_IMPORT_PATH /opt/Qt${QT}/${QT}/gcc_64/qml/  ENV SHELL=/bin/bash CMD bash  USER user WORKDIR /home/user CMD bash

В эту сборку добавили отдельного пользователя user, поддержку ввода на русском языке и возможность переключаться по alt+cntrl.

Два файла: qt-opensource-linux-x64-5.11.1.run и qt-installer-noninteractive.qs скопировали в контейнер, в папку /tmp. После установки подчистили за собой место. Сразу сохранили в контейнер информацию об адресе х-сервера. В случае, когда после перезагрузки компьютера адрес изменится, мы его установим через параметры запуска контейнера.

Создаем образ, в конце добавляем путь к каталогу где лежат дистрибутив qt и скрипт .qs:

docker build -t offline_qtcr -f Dockerfile d:\Distrib\Qt\single\qreator_linux\

Запускаем:

docker run --name offqtcont -it offline_qtcr /opt/Qt5.11.0/Tools/QtCreator/bin/qtcreator.sh

Запустился qtcreator:

Можем при запуске не указывать команду запуска самого qtcreator, тогда откроется консоль и в ней уже можем ввести путь до исполняемого файла.

Заключение.

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


ссылка на оригинал статьи https://habr.com/ru/company/stc_spb/blog/657927/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *