Задать вопрос
Пользователь пока ничего не рассказал о себе

Наибольший вклад в теги

Все теги (1)

Лучшие ответы пользователя

Все ответы (1)
  • Как запустить несколько Docker-контейнеров с MySQL на одном порту и на одном хосте?

    @WebMonet
    Как решить вашу проблему?

    Дано - хост 1.2.3.4
    К нему привязаны домены foo.com, bar.com, baz.org. За каждым доменом закреплен сайт, который состоит из PHP, Nginx, MySQL (далее по вкусу). Назовем каждый сайт приложением. С помощью docker-compose можно запустить примерно вот такой конфиг

    version: "3.6"
    networks:
        app_network:
            name: foo_net
    
    services:
    
        nginx: 
            ports:
                -   target: 80
                    published: ${APP_PORT}
                    protocol: tcp
                    mode: host
            volumes:
                - ./:/var/www/html
            networks:
                - app_network      
    
        php:
            build:
             ...
            volumes:
                - ./:/var/www/html
            networks:
                - app_network
    
        db_server: 
            ports:
                -   target: 3306
                    published: '${APP_DB_PORT}'
            volumes:
                - ../mysql:/var/lib/mysql
            networks:
                - app_network
    
        node:
            depends_on:
                - php
            volumes:
                - ./:/var/www/html:rw
            command: npm install && npm run dev
            networks:
                - app_network


    Прикол в том, что все контейнеры одного приложения видят друг-друга в пределах одной виртуальной сети (app_network) даже без EXPOSE. EXPOSE связывает целевой порт контейнера с портом хоста (1.2.3.4) Без него nginx прекрасно видит PHP-FPM по порту 9000 (только имя контейнера должно быть правильным. В данном примере это будет php:9000)
    ....
    location ~* \.php$ {
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            fastcgi_pass<b> php:9000;</b>
            fastcgi_index index.php;
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
            fastcgi_param PATH_INFO $fastcgi_path_info;
    ...


    , PHP видит mysql по дефолтному порту 3306. Возникает вопрос, зачем же мы прокинули на хост какой-то ${APP_DB_PORT} от db_server. ответ прост - по этому порту можно подключиться напрямую к БД из своей любимой IDE, phpMyAdmin и.д. Соответственно, внешний порт БД для foo.com может быть 33061, для bar.com 33062 а для baz.org - 33063.
    Такая же история и с NGINX, который выступает у нас фронтендом приложений. Мы слушаем на хосте ${APP_PORT} и прокидываем из него все в 80 порт соответствующего контейнера. Получается, что по порту 1080 нам ответит foo.com, 1180 - bar.com, а 1280 - baz.org. В итоге, у нас уже на одном хосте крутятся 3 приложения / сайта, которые не мешают друг-другу (и даже не подозревают о существовании друг-друга)
    Остается самая малость - выпустить их в интернет. Тут все совсем просто: поднимаете nginx/haproxy/etc и говорите им, что для хостнейма foo.com используй апстрим 127.0.0.1:1080, для bar.com 127.0.0.1:1180 и угадайте сами, что для baz.org. Внимательно отнеситесь к слешам на конце апстрима. Документация вам расскажет, когда они нужны, а когда нет.
    Откуда взялись переменные типа ${APP_PORT} ? Их можно задавать в .env файликах, которые будут лежать рядом с docker-compose.yml.

    APP_PORT=1180
    APP_DB_PORT=33062


    В итоге, всех встречает шлюз, в соответствии с именем хоста раскидывает по апстримам, а внутри приложения контейнеры уже сами видят друг-друга.
    Схема 100% рабочая, но не без изъянов. Для продакшена повнимательнее изучите нюансы. За подробностями приходите в личку и на мой курс про докер для PHP-разработчиков.
    Ответ написан
    3 комментария