В современных условиях Я, как и другие, зачастую работаю с разнородной инфраструктурой, включающей:
ноутбуки;
смартфоны и планшеты;
физические серверы;
виртуальные серверы;
контейнерные среды.

Возникает закономерный вопрос: какая операционная система и среда разработки обеспечат максимальную продуктивность при работе с таким парком оборудования?
На основании многолетнего опыта эксплуатации различных платформ сделан вывод, что Windows остаётся наиболее функциональной базовой операционной системой для повседневного использования. Но в статье хочу как раз рассказать, что неважно какая ОС на хосте.
Поскольку большинство современных проектов развёртывается в Docker, оптимальная среда разработки должна обеспечивать:
совместимость с Linux‑окружением;
интеграцию с инструментами контейнеризации;
удобство отладки и тестирования.
Практическая реализация
Этап 1. Виртуальная машина Ubuntu

Первым шагом стала организация виртуальной машины с Ubuntu на ноутбуке: попробовал Hyper‑V, VMWare и VirtualBox, пробовал IDE запускать внутри ВМ, но потом перешел на подключение по SSH, а IDE запускать на хосте (в этом плане лучше всего подходит Hyper‑V).
Преимущества подхода:
изоляция среды разработки от основной ОС;
возможность быстрого клонирования/восстановления;
тестирование в «чистом» Linux‑окружении.
Этап 2. Контейнерная среда с удалённым доступом
Для повышения эффективности был реализован переход на контейнерную модель:
1. Создание Docker‑контейнера с предустановленным окружением:
Dockerfile
FROM ubuntu:24.04
RUN apt-get update
RUN apt-get install \
pip \
openssh-server \
git \
sshpass \
python3.13-full -y && rm -rf /var/cache/apt
# Настройка SSH‑доступа:
RUN userdel -r ubuntu
RUN useradd -rm -d /home/ubuntu -s /bin/bash -g root -G sudo -u 1000 dev
RUN echo 'dev:dev' | chpasswd
RUN service ssh start
EXPOSE 22
CMD ["/usr/sbin/sshd","-D"] 2. Запуск на сервере:
Запущен контейнер был на железном сервере с внешним IP и я мог подключаться к нему из любой точки мира. Минимальные настройки безопасности, конечно же были, но как известно, после перезапуска или редеплоя файловая система контейнера бы обнулялась. Задача была решена монтированием соответствующих папок и файлов через файл:
docker-compose.yml
services:
mi113r:
image: "registry.gitlab.com/devops1505017/vscode-python/dev_platform:1.2"
tty: true
logging:
driver: "json-file"
options:
max-size: "200k"
max-file: "10"
restart: always
ports:
- "ХХХ:22"
volumes:
- /home/dev/projects:/home/ubuntu/projects
- /home/dev/conf/ssh_config.conf:/etc/ssh/sshd_config.d/ххх.conf
- /home/dev/conf/.ssh/:/home/ubuntu/.ssh/
- /home/dev/conf/.gitconfig:/home/ubuntu/.gitconfigСамые важные здесь – это настройки безопасности:
- /home/dev/conf/ssh_config.conf:/etc/ssh/sshd_config.d/ssa.conf
- /home/dev/conf/.ssh/:/home/ubuntu/.ssh/
Но это уже совсем другая история
3. Интеграция с VS Code:
-
установка ��асширения Remote‑SSH;

-
добавление хоста в конфигурацию;

Этап 3. Docker-CLI внутрь контейнера для разработки
Для подключения по SSH и разработки этого было достаточно, но потом мне захотелось собирать контейнеры и выполнять команды docker (с использование docker context) прямо из среды разработки без переключений и я интегрировал docker-cli внутрь docker контейнера (да получился докер в докере, но это работает)
расширенный Dockerfile:
FROM ubuntu:24.04
RUN apt-get update
RUN apt-get install \
nano \
wget \
pip \
openssh-server \
git \
sudo \
make \
sshpass \
apt-transport-https \
ca-certificates \
curl \
gnupg \
lsb-release \
software-properties-common \
python3.13-full \
gcc -y \
&& add-apt-repository -y ppa:deadsnakes/ppa \
&& rm -rf /var/cache/apt
RUN wget -O- https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor | sudo tee /etc/apt/keyrings/docker.gpg > /dev/null
RUN echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu jammy stable"| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
RUN sudo apt update
RUN sudo apt-get install docker-ce docker-ce-cli containerd.io -y && rm -rf /var/cache/apt
RUN userdel -r ubuntu
RUN useradd -rm -d /home/ubuntu -s /bin/bash -g root -G sudo -u 1000 dev
RUN echo 'dev:dev' | chpasswd
RUN service ssh start
EXPOSE 22
CMD ["/usr/sbin/sshd","-D"]Также необходимо будет добавить папки монтирования в docker-compose.yml, чтобы обеспечить сохранение настроек при перезапуске:
- /home/dev/conf/.docker/:/home/ubuntu/.docker/
- /home/dev/conf/etc/docker/:/etc/docker/
Этап 4. Code Anywhere
В короткие поездки я могу не взять с собой ноутбук, только планшет и вот тут самое интересное … я перепробовал уйму IDE, даже писал кусочки кода в vim подключившись по ssh, но это очень не удобно.
Ознакомившись со статьями:
- Пишите код везде. Настройте сервер кода с помощью VS Code Server
- Установка Visual Studio Code в облаке
Я решил проверить на практике, как это работает на самом деле … установить VSCode-server оказалось невероятно просто:
curl -fsSL https://code-server.dev/install.sh | sh
А вот запустить VSCode-server стандартным способом через systemctl внутри докера не получится, но оно нам и не нужно, можем запустить с выводом в консоль, главное объявить команду на этапе сборки image:
CMD ["/usr/bin/code-server", "--bind-addr", "0.0.0.0:8080", "--auth", "password"]
такой подход заблокировал запуск SSH, разрешить конкуренцию сервисов удалось с помощью скрипта на bash: запуск одновременно двух процессов (скрипт для Dockerfile):
RUN echo '#!/bin/bash' > /start.sh && \
echo '/usr/sbin/sshd -D &' >> /start.sh && \
echo 'P1=$!' >> /start.sh && \
echo '/usr/bin/code-server --bind-addr 0.0.0.0:8080 --auth password &' >> /start.sh && \
echo 'P2=$!' >> /start.sh && \
echo 'wait $P1' >> /start.sh && \
echo 'wait $P2' >> /start.sh && \
chmod +x /start.sh
EXPOSE 22 8080
ENTRYPOINT ["/start.sh"]
Теперь CodeAnyWhere зазвучал по новому, полноценно.
Этап 5. Доменное имя
С HTTP в nginx проблем не должно возникнуть:
server {
listen 80;
listen [::]:80;
server_name youdomain.oonline;
server_tokens off;
location /.well-known/acme-challenge/ {
root /var/www/certbot/;
}
location / {
return 301 https://youdomain.oonline$request_uri;
}
}
но эта конструкция мне нужна только чтобы получить сертификат Lets Encrypt. А вот с HTTPS пришлось повозиться … после запуска появлялась ошибка

решается эта ошибка четырьмя строчками в “location /” :
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection upgrade;
proxy_set_header Accept-Encoding gzip;
nginx.conf (конструкция целиком)
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name youdomain.oonline;
ssl_certificate /etc/letsencrypt/live/youdomain.oonline/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/youdomain.oonline/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 24h;
location / {
proxy_pass http://vscode-server:8080;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection upgrade;
proxy_set_header Accept-Encoding gzip;
client_max_body_size 0;
}
}Что в итоге:
Контейнер с Ubuntu, к которому можно подключится по SSH.
При подключении к контейнеру мы можем использовать docker CLI и собирать другие контейнеры.
У этого «комбайна» для разработки есть WEB‑интерфейс с полноценным VSCode, в котором есть отладка и доступ к терминалу.
Есть полноценный IDE, который запускается на планшете (будь то iOS или Android)
pavelmvl
Из статьи не понятно для чего нужен ssh сервер внутри контейнера, codeserver выполняет такие же функции, и при этом вам не нужно запускать 2 сервиса в контейнере.
Если нет каких-либо требований по реверс прокси, то я советовал бы посмотреть в сторону caddy вместо nginx. Он умеет сам, без certboot обновлять letsencrypt сертификаты.
Есть вопросы и к Dockerfile. Он сильно не оптимальный. Если интересно, то можно разобрать отдельно.