{
    "version": "https:\/\/jsonfeed.org\/version\/1",
    "title": "Максим Кузнецов: заметки с тегом docker",
    "_rss_description": "Простыми словами о веб-разработке",
    "_rss_language": "ru",
    "_itunes_email": "",
    "_itunes_categories_xml": "",
    "_itunes_image": "",
    "_itunes_explicit": "",
    "home_page_url": "https:\/\/maxkuznetsov.ru\/tags\/docker\/",
    "feed_url": "https:\/\/maxkuznetsov.ru\/tags\/docker\/json\/",
    "icon": "https:\/\/maxkuznetsov.ru\/user\/userpic@2x.jpg?1586398004",
    "author": {
        "name": "Максим Кузнецов",
        "url": "https:\/\/maxkuznetsov.ru\/",
        "avatar": "https:\/\/maxkuznetsov.ru\/user\/userpic@2x.jpg?1586398004"
    },
    "items": [
        {
            "id": "34",
            "url": "https:\/\/maxkuznetsov.ru\/all\/docker-localhost-and-https\/",
            "title": "Как подружить docker, localhost и HTTPS",
            "content_html": "<p>Когда разрабатываешь веб-сервис, который крутится на проде по HTTPS, есть большой соблазн не запариваться и работать локально по HTTP. Потому что так проще, да и в целом же всё работает плюс-минус одинаково. Если сервис простой, то скорее всего никаких проблем не всплывёт, но если сервис не монолитный и зависит от внешних сервисов или сам предоставляет АПИ клиентам, то проблемы с CORS неизбежны. И обычно эти проблемы обнаруживаются слишком поздно — либо на стейджинге, либо даже после релиза на продакшен.<\/p>\n<p>Браузер начинает ругаться, что запросы с HTTPS на HTTP или наоборот не безопасны, сторонние сервисы перестают отвечать, так как по HTTP работали только тестовые стенды, с которыми вы и работали.<\/p>\n<p>Решение простое — нужно не лениться и максимально приблизить локальную среду к боевой. Благо это задача из серии один раз сделал и используешь для всех последующих проектов.<\/p>\n<h2>Docker на продакшене<\/h2>\n<p class=\"remark\">\r\nЕсли у вас продакшен без Docker, то вам поможет статья — <a href=\"https:\/\/maxkuznetsov.ru\/all\/nginx-free-ssl\/\">Как получить бесплатный SSL-сертификат и установить его на Nginx<\/a>.\r\n<\/p>\n<p>В этой статье я рассматриваю только локальную сборку через docker-compose, потому что на продакшене, как ни странно, это немного проще. Достаточно выполнить понятную инструкцию <a href=\"https:\/\/certbot.eff.org\/lets-encrypt\/ubuntuxenial-nginx\">по настройке Certbot<\/a> и\/или добавить соответствующий  <a href=\"https:\/\/hub.docker.com\/r\/certbot\/certbot\/\">докер-образ с Docker Hub<\/a>.<\/p>\n<h2>Docker на localhost<\/h2>\n<p class=\"remark\">См. как запустить сайт через docker-compose на примере <a href=\"https:\/\/maxkuznetsov.ru\/all\/egeya-docker\/\">докеризации Эгеи<\/a>.<\/p>\n<p>На локалхосте Certbot не подойдёт, так как ему нужно реально существующее доменное имя и доступный через интернет сайт. Поэтому прописать локальный адрес в \/etc\/hosts не поможет. Решение — выпустить свой самоподписанный сертификат. Да, он не будет приниматься никем, кроме нашей системы, но для локальной разработки этого и не нужно.<\/p>\n<h3>Создаём доменное имя<\/h3>\n<p>Во-первых, создадим локально доменное имя, чтобы оно было похожим на боевое, а не обычный и скучный localhost. Например, docker.loc для основного сайта и api.docker.loc для API:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">$ sudo vim \/etc\/hosts\r\n127.0.0.1       localhost\r\n127.0.0.1       docker.loc\r\n127.0.0.1       api.docker.loc\r\n...<\/code><\/pre><p>Если для вашего сервиса необходимо несколько доменов, то пропишите их ниже по аналогии.<\/p>\n<h3>Выпускаем свой SSL-сертификат<\/h3>\n<p>Для реальных сайтов SSL-сертификаты выдаются специальными сертификационными центрами за деньги. За это они потом могут подтвердить верность домена по запросу любого браузера. Мы же выпустим свой сертификат и сами его подтвердим.<\/p>\n<p>SSL-сертификат создаётся одной командой и состоит из двух частей: публичного сертификата и секретного ключа.<\/p>\n<pre class=\"e2-text-code\"><code class=\"bash\">openssl req -x509 -out docker.loc.crt -keyout docker.loc.key \\\r\n  -newkey rsa:2048 -nodes -sha256 \\\r\n  -subj '\/CN=docker.loc' -extensions EXT -config &lt;( \\\r\n   printf &quot;[dn]\\nCN=docker.loc\\n[req]\\ndistinguished_name = dn\\n[EXT]\\nsubjectAltName=DNS:docker.loc\\nkeyUsage=digitalSignature\\nextendedKeyUsage=serverAuth&quot;)<\/code><\/pre><p>Файлы docker.loc.crt и docker.loc.key будут сохранены в той папке, откуда вы запускаете команду.<\/p>\n<h3>Добавляем сертификаты в ОС<\/h3>\n<p>Ниже пример, как это сделать на Mac OS X.<\/p>\n<ol start=\"1\">\n<li>Найдите сертификат docker.loc.crt в Finder (или можно в нужной папке консоли ввести «open .»)<\/li>\n<li>Дважды кликните по нему, появится окно.<\/li>\n<\/ol>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/maxkuznetsov.ru\/pictures\/Screen-Shot-2020-05-26-at-22.04.11.png\" width=\"1294\" height=\"834\" alt=\"\" \/>\n<\/div>\n<ol start=\"3\">\n<li>Введите пароль администратора<\/li>\n<li>Теперь нужно найти этот сертификат в Keychain Access и выбрать Trust Always<\/li>\n<\/ol>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/maxkuznetsov.ru\/pictures\/Screen-Shot-2020-05-26-at-22.09.28.png\" width=\"1870\" height=\"1386\" alt=\"\" \/>\n<\/div>\n<h3>Добавляем сертификаты в docker-compose сборку<\/h3>\n<p>Сертификаты нужно положить в контейнер с веб-сервером. Я приведу пример для Nginx и сборки по типу <a href=\"https:\/\/github.com\/pluseg\/e2-docker.\">https:\/\/github.com\/pluseg\/e2-docker.<\/a><\/p>\n<h3>Расположение сертификатов и конфигов<\/h3>\n<p>В этой сборке папки из app\/docker\/nginx монтируются прямо в nginx-контейнер. Поэтому удобно расположить файлы так:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">&lt;project root&gt;\r\n- app\r\n--- docker\r\n----- nginx\r\n------- conf.d\r\n--------- docker.loc.conf\r\n------- ssl\r\n--------- docker.loc.crt\r\n--------- docker.loc.key<\/code><\/pre><h3>Пример docker.loc.conf (проект на PHP + Symfony)<\/h3>\n<pre class=\"e2-text-code\"><code class=\"yaml\"># лучше с php соединять через socket\r\nupstream php-upstream { server web:9000; }\r\n\r\n# Редиректим HTTP на HTTPS\r\nserver {\r\n       listen         80;\r\n       listen    [::]:80;\r\n       server_name    docker.loc;\r\n       return         301 https:\/\/$server_name$request_uri;\r\n}\r\n\r\nserver {\r\n    listen 443 ssl;\r\n    listen [::]:443 ssl;\r\n\r\n    root \/var\/www\/html\/docs;\r\n\r\n    server_name            docker.loc;\r\n    ssl_certificate          \/etc\/nginx\/ssl\/docker.loc.crt;\r\n    ssl_certificate_key   \/etc\/nginx\/ssl\/docker.loc.key;\r\n    ssl_protocols           TLSv1 TLSv1.1 TLSv1.2;\r\n    ssl_ciphers         EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;\r\n\r\n    location \/ {\r\n    \ttry_files $uri \/index.php$is_args$args;\r\n    }\r\n\r\n    location ~ ^\/(index|app|app_dev|config)\\.php(\/|$) {\r\n        fastcgi_pass php-upstream;\r\n        fastcgi_split_path_info ^(.+\\.php)(\/.*)$;\r\n        include fastcgi_params;\r\n        fastcgi_param  SCRIPT_FILENAME $realpath_root$fastcgi_script_name;\r\n        fastcgi_param DOCUMENT_ROOT $realpath_root;\r\n        fastcgi_read_timeout 300;\r\n    }\r\n\r\n    error_log \/var\/log\/nginx\/docker.loc-error.log;\r\n    access_log \/var\/log\/nginx\/docker.loc-access.log;\r\n}<\/code><\/pre><h3>Пример docker-compose.yml<\/h3>\n<p>Добавляем 443 порт и несколько volume с конфигами и сертификатами.<\/p>\n<pre class=\"e2-text-code\"><code class=\"yaml\">version: '3.2'\r\nservices:\r\n    ...\r\n    nginx:\r\n        image: nginx:latest\r\n        ports:\r\n            - 80:80\r\n            - 443:443\r\n        volumes:\r\n            - .\/app\/docker\/nginx\/conf.d:\/etc\/nginx\/conf.d\r\n            - .\/app\/docker\/nginx\/ssl:\/etc\/nginx\/ssl\r\n            - .\/:\/var\/www\/html\r\n            - .\/var\/logs\/nginx:\/var\/log\/nginx\r\n        command: \/bin\/bash -c &quot;exec nginx -g 'daemon off;'&quot;<\/code><\/pre><h3>Запускаем и проверяем<\/h3>\n<pre class=\"e2-text-code\"><code class=\"\">docker-compose up -d --build<\/code><\/pre>",
            "date_published": "2020-05-26T22:29:08+03:00",
            "date_modified": "2020-05-26T22:28:48+03:00",
            "image": "https:\/\/maxkuznetsov.ru\/pictures\/Screen-Shot-2020-05-26-at-22.04.11.png",
            "_date_published_rfc2822": "Tue, 26 May 2020 22:29:08 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "34",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css"
                ],
                "og_images": [
                    "https:\/\/maxkuznetsov.ru\/pictures\/Screen-Shot-2020-05-26-at-22.04.11.png",
                    "https:\/\/maxkuznetsov.ru\/pictures\/Screen-Shot-2020-05-26-at-22.09.28.png"
                ]
            }
        },
        {
            "id": "29",
            "url": "https:\/\/maxkuznetsov.ru\/all\/egeya-docker\/",
            "title": "Запускаем Эгею через Docker и забываем про технические проблемы на 10 лет вперёд",
            "content_html": "<div class=\"e2-text-picture\">\n<img src=\"https:\/\/maxkuznetsov.ru\/pictures\/Screen-Shot-2020-04-28-at-01.29.37.png\" width=\"1205\" height=\"658\" alt=\"\" \/>\n<\/div>\n<p class=\"remark\"><b>Про работу с Docker<\/b> можно посмотреть <a href=\"https:\/\/maxkuznetsov.ru\/all\/docker-basic\/\">часовое видео<\/a>. С Docker вам не нужно заботиться о конфигурациях веб-сервера, базы данных и правах доступа к файлам и папкам. Одна команда — и готово.<\/p>\n<p>В официальной документации Эгеи есть две ссылки на запуск блога с помощью Докера, но оба способа имеют свои недостатки. По крайней мере один из них устарел и просто не заведётся из коробки, плюс используется старый, медленный ПХП 5, а второй использует веб-сервер caddle, который не столь популярен и хорошо описан, как Nginx или официально поддерживаемый Эгеей Apache.<\/p>\n<h2>Блог за 5 шагов<\/h2>\n<p>Вот, что вам нужно, чтобы установить последнюю версию блога.<\/p>\n<ol start=\"1\">\n<li>Установленные на целевой машине docker и docker-compose — это может быть и локальная машина, и продакшн. А также наличие домена, если поднимаете на продакшене.<\/li>\n<li>Склонировать репозиторий <a href=\"https:\/\/github.com\/pluseg\/e2-docker\">https:\/\/github.com\/pluseg\/e2-docker<\/a><\/li>\n<\/ol>\n<pre class=\"e2-text-code\"><code class=\"\">git clone git@github.com:pluseg\/e2-docker.git \/path\/to\/blog\/folder<\/code><\/pre><ol start=\"3\">\n<li>Создать файл .env<\/li>\n<\/ol>\n<pre class=\"e2-text-code\"><code class=\"\">cp .env.example .env<\/code><\/pre><ol start=\"4\">\n<li>И указать в нём нужные версии PHP, MySQL, Эгеи (на сегодняшний день они актуальные и их менять и не надо) и домен VIRTUAL_HOST (для локали можно оставить localhost.<\/li>\n<li>Запускаем всё это хозяйство с помощью docker-compose<\/li>\n<\/ol>\n<pre class=\"e2-text-code\"><code class=\"\">docker-compose up -d --build<\/code><\/pre><ol start=\"5\">\n<li>Заходим на домен, указанный в VIRTUAL_HOST, и заполняем небольшую форму<\/li>\n<\/ol>\n<pre class=\"e2-text-code\"><code class=\"\">DB Host: db\r\n   DB User: root\r\n   DB Pass: egeya\r\n   DB Database: &lt;выбрать из списка &quot;egeya&quot;&gt;\r\n   Admin pass: &lt;укажите ваш админский пароль&gt;<\/code><\/pre><ol start=\"6\">\n<li>Готово.<\/li>\n<\/ol>\n<h2>Дополнительные плюшки<\/h2>\n<p>В этой сборке я вынес версии всех зависимостей в .env файл, так что теперь обновить версию блога, ПХП или mysql — дело одной минуты. Достаточно обновить их в .env файле и перезапустить контейнеры с флагом пересборки:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">docker-compose up -d --build<\/code><\/pre><p>Если понадобится перенести блог в другое место — не проблема. Достаточно перенести папку с блогом куда нужно и запустить ту же самую команду docker-compose.<\/p>\n<p>Все файлы, которые должны сохраниться между обновлениями сохранятся. Они лежат в папке .\/data:<\/p>\n<ul>\n<li>data\/pictures — картинки<\/li>\n<li>data\/user — всё, что касается пользователя, включая shared шаблоны и настройки<\/li>\n<li>data\/theme — ваша кастомная тема, если понадобится. Она добавляется в папку к остальным комплектным темам \/themes<\/li>\n<li>data\/mysql — данные из базы<\/li>\n<\/ul>\n",
            "date_published": "2020-04-28T01:37:47+03:00",
            "date_modified": "2020-05-20T22:12:24+03:00",
            "image": "https:\/\/maxkuznetsov.ru\/pictures\/Screen-Shot-2020-04-28-at-01.29.37.png",
            "_date_published_rfc2822": "Tue, 28 Apr 2020 01:37:47 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "29",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css"
                ],
                "og_images": [
                    "https:\/\/maxkuznetsov.ru\/pictures\/Screen-Shot-2020-04-28-at-01.29.37.png"
                ]
            }
        },
        {
            "id": "14",
            "url": "https:\/\/maxkuznetsov.ru\/all\/docker-basic\/",
            "title": "Принципы работы docker и примеры использования docker-compose",
            "content_html": "<p>Артём Матяшов записал отличный полуторачасовой урок про основы докера. Можно посмотреть на x1.5 за час.<\/p>\n<div style=\"max-width: 640px;\"><div class=\"e2-text-video\">\n<iframe src=\"https:\/\/www.youtube.com\/embed\/QF4ZF857m44\" frameborder=\"0\" allowfullscreen><\/iframe><\/div>\n<\/div><p>Подойдёт начинающим бэкендерам, а также фронтендерам, верстальщикам и всем, кому нужно развернуть проект на один раз и удалить без захламления системы.<\/p>\n<p>Однозначно лайк!<\/p>\n",
            "date_published": "2020-03-23T13:32:17+03:00",
            "date_modified": "2020-04-14T19:08:18+03:00",
            "image": "https:\/\/maxkuznetsov.ru\/pictures\/remote\/youtube-QF4ZF857m44-cover.jpg",
            "_date_published_rfc2822": "Mon, 23 Mar 2020 13:32:17 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "14",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [],
                "og_images": [
                    "https:\/\/maxkuznetsov.ru\/pictures\/remote\/youtube-QF4ZF857m44-cover.jpg"
                ]
            }
        },
        {
            "id": "12",
            "url": "https:\/\/maxkuznetsov.ru\/all\/docker-on-mac-speed\/",
            "title": "Как ускорить docker-compose на Mac OS X — docker-sync",
            "content_html": "<p>Хорошая статья про настройку docker-sync — короче и ёмче, чем в официальной документации:<br \/>\n<a href=\"https:\/\/dev.to\/kovah\/cut-your-docker-for-mac-response-times-in-half-with-docker-sync-1e8j\">https:\/\/dev.to\/kovah\/cut-your-docker-for-mac-response-times-in-half-with-docker-sync-1e8j<\/a><\/p>\n<h3>1. Установка через терминал<\/h3>\n<pre class=\"e2-text-code\"><code class=\"bash\">\r\ngem install --user-install docker-sync\r\n# or globally via\r\nsudo gem install docker-sync\r\n<\/code>\n<\/pre>\n<h3>2. Добавить файл <span style=\"font-family: monospace;\">docker-sync.yml<\/span> в корень проекта (пример для Symfony)<\/h3>\n<pre class=\"e2-text-code\"><code class=\"yaml\">\r\nversion: \"2\"\r\n\r\noptions:\r\n    compose-dev-file-path: 'docker-compose-sync.yml' # Если хочется изменить дефолтный файл docker-compose-dev.yml\r\nsyncs:\r\n    PROJECT-data-sync:  # Это надо заменить на любое уникальное имя\r\n        src: '.\/'\r\n        host_disk_mount_mode: 'cached'\r\n        sync_excludes:\r\n            - '.git'\r\n            - '.idea'\r\n            - 'app\/cache\/*'\r\n            - 'app\/logs\/*'\r\n<\/code>\n<\/pre>\n<h3>3. Добавить файл <span style=\"font-family: monospace;\">docker-compose-sync.yml<\/span> (или <span style=\"font-family: monospace;\">*-dev.yml<\/span> по умолчанию) в корень проекта:<\/h3>\n<pre class=\"e2-text-code\"><code class=\"yaml\">\r\nversion: '3.2'\r\n\r\nservices:\r\n    web:\r\n        volumes:\r\n            - .\/composer.json:\/var\/www\/html\/composer.json\r\n            - .\/composer.lock:\/var\/www\/html\/composer.lock\r\n            - PROJECT-data-sync:\/var\/www\/html:nocopy\r\n\r\nvolumes:\r\n    PROJECT-data-sync:\r\n        external: true\r\n<\/code>\n<\/pre>\n<h3>4. Запускаем в терминале в корне проекта<\/h3>\n<pre class=\"e2-text-code\"><code class=\"bash\">\r\ndocker-sync start\r\n# нужно подождать, пока всё синхронизируется\r\ndocker-compose -f docker-compose.yml -f docker-compose-sync.yml up -d\r\n<\/code>\n<\/pre>\n<p>Запуск через <span style=\"font-family: monospace;\">docker-sync-stack start<\/span> делает две команды выше, но остаётся висеть в консоли, а не уходит в фоновые процессы.<\/p>\n<p>Чтобы остановить, делаем ровно обратное<\/p>\n<pre class=\"e2-text-code\"><code class=\"bash\">\r\ndocker-compose stop\r\ndocker-sync stop\r\n<\/code>\n<\/pre>\n",
            "date_published": "2020-03-20T16:33:26+03:00",
            "date_modified": "2020-04-02T14:11:29+03:00",
            "_date_published_rfc2822": "Fri, 20 Mar 2020 16:33:26 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "12",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css"
                ],
                "og_images": []
            }
        },
        {
            "id": "11",
            "url": "https:\/\/maxkuznetsov.ru\/all\/kak-udalit-vsyo-chto-sozdal-docker-compose\/",
            "title": "Как удалить всё, что создал docker-compose",
            "content_html": "<pre class=\"e2-text-code\"><code class=\"\">cd path\/to\/project\r\ndocker-compose stop\r\ndocker-compose down -v --rmi all --remove-orphans<\/code><\/pre>",
            "date_published": "2020-03-20T01:16:51+03:00",
            "date_modified": "2020-04-09T02:32:06+03:00",
            "_date_published_rfc2822": "Fri, 20 Mar 2020 01:16:51 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "11",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css"
                ],
                "og_images": []
            }
        }
    ],
    "_e2_version": 3559,
    "_e2_ua_string": "E2 (v3559; Aegea)"
}