Введение.
В основном, 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+ctrl.
Два файла: 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, то по такому же принципу можно в докере развернуть любое графическое приложение.
