<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Docker on Ponfertato</title><link>https://ponfertato.potatoenergy.ru/tags/docker/</link><description>Recent content in Docker on Ponfertato</description><generator>Hugo -- gohugo.io</generator><language>ru</language><copyright>© 2019-2026 Ponfertato</copyright><atom:link href="https://ponfertato.potatoenergy.ru/tags/docker/index.xml" rel="self" type="application/rss+xml"/><item><title>Hugo: Архитектура статических сайтов и CI/CD</title><link>https://ponfertato.potatoenergy.ru/projects/hugo-workflow/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://ponfertato.potatoenergy.ru/projects/hugo-workflow/</guid><description>&lt;p&gt;Использование Hugo для генерации статических сайтов позволяет достичь максимальной производительности при минимальных накладных расходах. Все проекты на стеке &lt;code&gt;*.potatoenergy.ru&lt;/code&gt; используют единую методологию сборки, конфигурации и деплоя.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ключевые принципы&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;🔹 Декларативная конфигурация через &lt;code&gt;hugo.toml&lt;/code&gt; и &lt;code&gt;config/_default/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;🔹 Мультиязычность через &lt;code&gt;translationKey&lt;/code&gt; без дублирования логики&lt;/li&gt;
&lt;li&gt;🔹 Наследование параметров через &lt;code&gt;cascade&lt;/code&gt; во фронтматтере&lt;/li&gt;
&lt;li&gt;🔹 Оптимизация ассетов через Hugo Pipes (минификация, фолбэки, хеширование)&lt;/li&gt;
&lt;li&gt;🔹 Изоляция окружения сборки через Docker&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;

&lt;h2 class="relative group"&gt;🗂 Структура проекта
 &lt;div id="-структура-проекта" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#-%d1%81%d1%82%d1%80%d1%83%d0%ba%d1%82%d1%83%d1%80%d0%b0-%d0%bf%d1%80%d0%be%d0%b5%d0%ba%d1%82%d0%b0" aria-label="Якорь"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;project/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── config/_default/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── hugo.toml # Базовые настройки: baseURL, theme, outputs
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── params.toml # Глобальные параметры темы и кастомные переменные
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── menus.toml # Конфигурация навигации
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── languages.*.toml # Локализация: displayName, copyright, author
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── content/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── {section}/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ ├── _index.{ru,en}.md # Страница-листинг с описанием раздела
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ └── {slug}/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ ├── index.{ru,en}.md # Контент с переводом через translationKey
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ └── assets/ # Ресурсы, привязанные к странице
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── _index.{ru,en}.md # Главная страница
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── layouts/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── _default/ # Шаблоны по умолчанию: single.html, list.html
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── partials/ # Переиспользуемые компоненты: head, footer, svg
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── shortcodes/ # Кастомные шорткоды: audio, toggle, icon
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── shortcodes/ # Переопределение шаблонов темы (при необходимости)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── static/ # Файлы, копируемые «как есть»: robots.txt, favicons
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── assets/ # Исходники для Hugo Pipes: CSS/JS для сборки
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└── docker-compose.yml # Окружение для локальной разработки&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;hr&gt;

&lt;h2 class="relative group"&gt;🌐 Мультиязычность без дублирования
 &lt;div id="-мультиязычность-без-дублирования" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#-%d0%bc%d1%83%d0%bb%d1%8c%d1%82%d0%b8%d1%8f%d0%b7%d1%8b%d1%87%d0%bd%d0%be%d1%81%d1%82%d1%8c-%d0%b1%d0%b5%d0%b7-%d0%b4%d1%83%d0%b1%d0%bb%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f" aria-label="Якорь"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;Связь переводов реализуется через &lt;code&gt;translationKey&lt;/code&gt; во фронтматтере:&lt;/p&gt;</description></item><item><title>Source-серверы на ARM64: Docker-образы для игр</title><link>https://ponfertato.potatoenergy.ru/projects/source-servers-arm64/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://ponfertato.potatoenergy.ru/projects/source-servers-arm64/</guid><description>&lt;p&gt;Серия Docker-образов для запуска серверов на базе Source Engine на архитектурах ARM64 (Orange Pi, Raspberry Pi 4/5, AWS Graviton).&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Репозиторий&lt;/th&gt;
 &lt;th&gt;Игра&lt;/th&gt;
 &lt;th&gt;Теги&lt;/th&gt;
 &lt;th&gt;Размер образа&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;a href="https://github.com/potatoenergy/garrysmod-docker" target="_blank" rel="noreferrer"&gt;garrysmod-docker&lt;/a&gt;&lt;/td&gt;
 &lt;td&gt;Garry&amp;rsquo;s Mod&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;latest&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;~2.1 GB&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;a href="https://github.com/potatoenergy/tf2-docker" target="_blank" rel="noreferrer"&gt;tf2-docker&lt;/a&gt;&lt;/td&gt;
 &lt;td&gt;Team Fortress 2&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;latest&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;~1.8 GB&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;a href="https://github.com/potatoenergy/css-docker" target="_blank" rel="noreferrer"&gt;css-docker&lt;/a&gt;&lt;/td&gt;
 &lt;td&gt;Counter-Strike: Source&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;latest&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;~1.6 GB&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;a href="https://github.com/potatoenergy/l4d2-docker" target="_blank" rel="noreferrer"&gt;l4d2-docker&lt;/a&gt;&lt;/td&gt;
 &lt;td&gt;Left 4 Dead 2&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;latest&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;~2.3 GB&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;a href="https://github.com/potatoenergy/hl2dm-docker" target="_blank" rel="noreferrer"&gt;hl2dm-docker&lt;/a&gt;&lt;/td&gt;
 &lt;td&gt;Half-Life 2: Deathmatch&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;latest&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;~1.5 GB&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;a href="https://github.com/potatoenergy/dods-docker" target="_blank" rel="noreferrer"&gt;dods-docker&lt;/a&gt;&lt;/td&gt;
 &lt;td&gt;Day of Defeat: Source&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;latest&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;~1.6 GB&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;a href="https://github.com/potatoenergy/l4d-docker" target="_blank" rel="noreferrer"&gt;l4d-docker&lt;/a&gt;&lt;/td&gt;
 &lt;td&gt;Left 4 Dead&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;latest&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;~2.0 GB&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Все образы используют единую архитектуру сборки и конфигурации.&lt;/p&gt;</description></item><item><title>Много проектов. Одна структура. Никакого хаоса.</title><link>https://ponfertato.potatoenergy.ru/projects/philosophy/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://ponfertato.potatoenergy.ru/projects/philosophy/</guid><description>&lt;p&gt;Когда проектов становится больше десяти, начинаются вопросы:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Где лежит конфиг для этого сервиса?&lt;/li&gt;
&lt;li&gt;Какую переменную окружения нужно задать при деплое?&lt;/li&gt;
&lt;li&gt;Почему один контейнер «ест» всю память, а другой молчит при падении?&lt;/li&gt;
&lt;li&gt;Как быстро развернуть всё это на новой машине?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ответ: &lt;strong&gt;единая структура, единые правила, единый подход&lt;/strong&gt;.&lt;/p&gt;
&lt;hr&gt;

&lt;h2 class="relative group"&gt;🗂 Единая структура репозиториев
 &lt;div id="-единая-структура-репозиториев" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#-%d0%b5%d0%b4%d0%b8%d0%bd%d0%b0%d1%8f-%d1%81%d1%82%d1%80%d1%83%d0%ba%d1%82%d1%83%d1%80%d0%b0-%d1%80%d0%b5%d0%bf%d0%be%d0%b7%d0%b8%d1%82%d0%be%d1%80%d0%b8%d0%b5%d0%b2" aria-label="Якорь"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;Каждый активный проект следует одному шаблону:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;project-name/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── compose.yaml # Единый формат: сервисы, сети, volumes, лимиты
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── stack.env # Переменные окружения (в .gitignore)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── README.md # Кратко: что делает, как запустить, какие порты
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── .github/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── workflows/ # CI: сборка, тесты, деплой (если нужно)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└── (опционально)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ├── Dockerfile # Если нужен кастомный образ
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ├── config/ # Конфиги приложений (не секреты)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; └── scripts/ # Утилиты: бэкап, миграция, проверка&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Почему это работает&lt;/strong&gt;:&lt;/p&gt;</description></item><item><title>Эволюция Docker-конфигураций: от разрозненных контейнеров к управляемым стекам</title><link>https://ponfertato.potatoenergy.ru/projects/docker-evolution/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://ponfertato.potatoenergy.ru/projects/docker-evolution/</guid><description>&lt;p&gt;Раньше каждый сервис жил в отдельном репозитории с минимальным &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Старый подход: garrysmod-server/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;services&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;garrysmod-server&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;image&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;ceifa/garrysmod:latest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ports&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#e6db74"&gt;&amp;#34;27015:27015&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;volumes&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;./garrysmod:/data&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;restart&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;unless-stopped&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Проблемы&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;❌ Нет контроля ресурсов - один сервис мог «съесть» всю память&lt;/li&gt;
&lt;li&gt;❌ Нет health checks - упавший сервис не детектировался&lt;/li&gt;
&lt;li&gt;❌ Нет лог-ротации - логи росли до заполнения диска&lt;/li&gt;
&lt;li&gt;❌ Нет изоляции сетей - все сервисы в &lt;code&gt;default&lt;/code&gt; сети&lt;/li&gt;
&lt;li&gt;❌ Обновление каждого сервиса вручную - высокий риск человеческой ошибки&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;

&lt;h2 class="relative group"&gt;Новый подход: стеки с явными контрактами
 &lt;div id="новый-подход-стеки-с-явными-контрактами" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%d0%bd%d0%be%d0%b2%d1%8b%d0%b9-%d0%bf%d0%be%d0%b4%d1%85%d0%be%d0%b4-%d1%81%d1%82%d0%b5%d0%ba%d0%b8-%d1%81-%d1%8f%d0%b2%d0%bd%d1%8b%d0%bc%d0%b8-%d0%ba%d0%be%d0%bd%d1%82%d1%80%d0%b0%d0%ba%d1%82%d0%b0%d0%bc%d0%b8" aria-label="Якорь"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;Теперь связанные сервисы группируются в единый репозиторий с общей конфигурацией:&lt;/p&gt;</description></item></channel></rss>