Кому эта статья может быть полезна?
Многие сегодня припарковали свои проекты на виртуальных серверах типа vps/vds или физическом сервере. И вот, по каким-то причинам, вы не хотели бы показывать свой код напрямую.
Если вы уже знаете про GitLab runner, Docker и registry – то можно пройти мимо и сберечь свое время. А кто не знает - добро пожаловать. Постараюсь, чтобы было не сложно.
Какие могут быть причины?
Например, до момента оплаты. Есть вариант разместить на своих серверах - но в таком случае, надо иметь эти сервера, платить за них. Да и клиенту как-то чувствительно будет греть сердце, что он что-то арендовал, и все его детище живет там у него.
Или если вы не хотите, чтобы кто-то сунулся в ваш код без вашего ведома - в попытке отодвинуть вас от проекта? Так некоторые и делают: "слушай, а что там за код у него, разберешься? Лови доступы."
Даже если вы - владелец этого сервера и вам просто нужно запустить кого то на ваш драгоценный инстанс, но так, чтобы он своими кривыми ручками там ничего такого не сделал. Умышленно или неумышленно.
Если одна из причин вам понравилась, тогда давайте вместе поиграем в легкий домашний DevOps (что еще за аббревиатура такая), который позволит вам не держать ваш код на сервере.
Статья это по сути инструкция, поэтому если вы сейчас прятать код не собираетесь, то будет немного скучновато. Сохраняйте в закладки и возвращайтесь, когда вы это захотите претворить в жизнь. Но если вы решительно настроены все делать сейчас, то продолжаем.
Итак, имеем:
Сервер одна штука.
Бесценный код. (Без разницы - Golang Django Next/Nuxt Larevel и так далее. Вы не хотите его держать на сервере в чистом виде, но при этом все должно работать именно на сервере.)
Регистрация в GitLab. Это можно сделать и в других местах, типа Yandex Cloud, но для простых смертных - GitLab самое то.
GitLab runner. (Это приложение такое, которое надо установить к вам на сервер.)
Docker (если не слышали что такое, то тут на хабре есть очень хорошие статьи на эту тему. Можно поискать через поиск)
Идея простая. Регистрируемся в GitLab. Создаем там свой репозиторий. Пушим код. Runner собирает образ и пушит его в Container Registry. А сервер сам потянет собранный образ и запустит его. В итоге, на сервере увидим только один файл с настройками запуска докера. То есть, в вашу жизнь должны войти всего два новых знания: 1. минимальное понимание работы с GitLab. 2. минимальное понимание работы с Docker. Кажется сейчас эти минимальные знания есть уже почти у всех кто умеет в push/pull, так что уверен будет несложно.
Даже если для кого то это звучит сейчас как абракадабра то на самом деле с вашей ИИ вы пройдете все шаги быстро и безболезненно. Просто дайте ей этот текст.
Чтобы здесь воду не лить и не тратить ваше время, описывать подробно каждый шаг смысла нет. Поэтому излагаю просто концепт.
Регистрируемся в GitLab, если еще этого не сделали.
Заводим туда свой проект и создаем репозиторий.
Там же нужно проверить или включить Container Registry (обычно все уже включено). Для этого переходим в Settings - General - Visibility - Container Registry.
Устанавливаем GitLab runner на вашем сервере и регистрируем его у вас в GitLab аккаунте.
Устанавливаем Docker на сервер.
На сервере сделать один раз docker login registry.gitlab.com. Логин — GitLab username, пароль — Personal Access Token с read_registry.
Итак, мы настроили все необходимое. Далее идут непосредственно файлы, которые покажут и расскажут GitLab и серверу куда и что.
Пишем в корне вашего проекта yml файл. Называем его .gitlab-ci.yml
Вот тут уже ИИ не доверяю, пишет часто почему-то с багами, поэтому берите рабочий пример ниже.
stages: - build - deploy variables: IMAGE_NAME: registry.gitlab.com/вашгит/вашпроект build_image: stage: build image: docker:25 services: - docker:25-dind variables: DOCKER_TLS_CERTDIR: "" script: - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - docker build -t $IMAGE_NAME:$CI_COMMIT_SHA -t $IMAGE_NAME:latest . - docker push $IMAGE_NAME:$CI_COMMIT_SHA - docker push $IMAGE_NAME:latest only: - main deploy_prod: stage: deploy tags: - prod script: - cd где храните инструкции для запуска - docker pull registry.gitlab.com/вашгит/названиеобраза:latest - docker compose up -d only: - main
Тут по файлу нужно немного дать комментарий. Этот код собирает Docker-образ на GitLab и пушит его в GitLab Container Registry. CI_REGISTRY_USER и CI_REGISTRY_PASSWORDВ — автоматические. И добавлю два важных дисклеймера.
Дисклеймер 1: тег "latest" нужен для упрощения деплоя. Это вам подходит, если у вас один сервер, один владелец и нет требований к откату “в одну команду”. Этот тег упростит процесс деплоя и снизит количество сущностей. Иначе, придеться поразбираться с управлением версиями. В реальных продакшн-сценариях обычно используют версионирование или ,так называемые, commit-теги, чтобы обеспечить удобный откат. Статья так глубоко заходить не планировала, поэтому пока просто latest.
Дисклеймер 2: Код, все таки, при желании, достать из контейнера можно, но с ограничениями. Любой человек с root-доступом к серверу и с доступом к docker socket все таки может сделать "docker export" и получить исходники. Но этот код не будет лежать в виде рабочего дерева проекта как у вас в репозитории. Для этого будет важно в финальный образ класть только артефакты (например, .output у Nuxt, dist у фронта, бинарник у Go) и не класть туда исходники. Тогда достать “код для сопровождения” уже будет существенно сложнее: это будут сборочные артефакты, иногда минифицированные, без исходных файлов, комментов, структуры и т.п. Это станет большим барьером для заинтерисованного лица. Придется думать про зависимости, сорс-мапы, символы, конфиги — всё это будет влиять, захочет ли кто-то во всем этом разбираться.
Далее создаем второй файл. Уже на сервере. Путь вы указали в строке из прошлого файла в строке "cd где храните инструкции для запуска". Файл назовем docker-compose.yml
services: front: image: registry.gitlab.com/вашгит/названиеобраза:latest ports: - "3000:3000" restart: unless-stopped
Тут, главное, обратите внимание на порт. Можно поменять в случае чего.
И последний файл. Инструкция для самого докера - Dockerfile. Который нужно положить рядом с .gitlab-ci.yml, то есть в корень проекта . Тут вам уже нужно сделать индивидуально под ваш проект. В данном случае, тоже обсудите с вашей ИИ как это сделать. Как пример, отправляю просто скриншотом, что бы бездумно не копировали.

Только не забудьте в промте написать, что вам нужно сделать так, чтобы в проекте не было исходников вашего кода.
Вот и все. Далее git add . && git commit -m «chtoto osmislennoe» && git push
Что-же произойдет? А ровно то, что я писал выше. Ваш код зальется в GitLab. GitLab возьмет ваш код и превратит его в образ. Образ улетит к вам на сервер. Сервер запустит образ и вуаля. Никакого чистого кода в виде файлов на вашем сервере.
Вы только что сделали те самые страшные буквы CI/CD которые можете записать в свое резюме.
В итоге, ваш код будет жить у вас в репозитории, а сервер — будет только лишь средой исполнения. И чем раньше эта граница станет явной, тем меньше сюрпризов возникнет при обновлениях, доступах и смене людей в проекте. Как уже говорил в статье, этот подход не делает код “неизвлекаемым” и не является системой защиты от человека с root-доступом. Но он решает практическую задачу: на сервере больше нет рабочего дерева проекта и прямого доступа к исходникам, а деплой становится воспроизводимым и управляемым. В результате, вы получаете понятный процесс обновлений, минимальный набор файлов на сервере и чёткую границу между разработкой и эксплуатацией. Для небольших команд и проектов этого часто более чем достаточно.
Рад был провести с вами время. До встречи. Вдруг, что еще интересного расскажу. Кто знает.
Всем лучиков добра и светлого настроения. С почтением к Хабровчанам, ваш DevOps.
