/b/ - Random

Свободное общение


New Reply
Name
×
Sage
Subject
Message
Files Max 5 files20MB total
Tegaki
Password
[New Reply]


Сап, коллеги!

В этот раз я сидел, работал с докером и решил, а что если я попробую запустить 2 веб сервера в разных контейнерах, где контейнер A будет лишь проксировать всё в контейнер B, а веб сервер в контейнере B будет возвращать html файл. 

Сделать это в докере? Сущий пустяк.
Что если воспользоваться тем, что нам даёт ядро линукса.

Для начала подготовим к этому нашу файловую систему:
mkdir -p /srv/containers
cd /srv/containers

Я захотел, чтобы наши контейнеры были на базе arch linux. Вы же можете скачать bootstrap версию другого дистрибутива на ваш вкус

wget https://mirror.i3d.net/pub/archlinux/iso/2025.08.01/archlinux-bootstrap-x86_64.tar.zst
tar -xf archlinux-bootstrap-x86_64.tar.zst
mv root.x86_64 arch-fs

Так, мы подготовили общую среду для наших контейнеров.
Теперь займёмся подготовкой тех директорий, которые не будут общими для наших контейнеров:
/var/log/access.log
/var/log/error.log
/var/www/html
/etc/nginx

Создадим раздельные директории:
mkdir -p container{1,2}/{var/{log,www/html},etc/nginx}
touch container{1,2}/var/log/access.log
touch container{1,2}/var/log/error.log
echo "Hello friend!" > container2/var/www/html/index.html

На этом наша файловая система почти готова, осталось доработать общую директорию arch-fs и дописать сами nginx.conf файлы

cp /usr/sbin/nginx arch-fs/usr/sbin
mkdir -p arch-fs/{var/{log,lib/nginx/body,www},etc/nginx}
Теперь пропишем минимальный nginx конфиг для второго контейнера.
В файле по директории container2/etc/nginx/nginx.conf:
events {

}

http {
        server {
                listen 80;
                server_name localhost;
                location / {
                        root /var/www/html;
                        index index.html;
                        try_files $uri $uri/ =404;
                }
        }
}

А затем и для первого контейнера.
В файле по директории container1/etc/nginx/nginx.conf:
events {

}

http {
        server {
                listen 80;
                server_name localhost;
                location / {
                        proxy_pass http://10.0.1.2:80;
                        proxy_set_header Host $host;
                        proxy_set_header X-Real-IP $remote_addr;
                        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                }
        }
}

Теперь перейдём к настройки сети.
Начнём с создания двух сетевых пространств имён:
ip netns add n_1
ip netns add n_2

Создадим виртуальный Ethernet интерфейс и пробросим один из его концов в n_1
ip link add nginx_out type veth peer name nginx_in
ip link set nginx_in netns n_1

После каждого этапа можно проверять резултат настройки через:
ip a

И в нужном сетевом пространстве имён:
ip netns exec n_1 ip a

Выдадим получившейся паре ipv4 адреса:
ip addr add 10.0.0.1/24 dev nginx_out
ip netns exec n_1 ip addr add 10.0.0.2/24 dev nginx_in

Вот мы и настроили наш туннель в n_1. Осталось всё это дело поднять:

ip link set nginx_out up
ip netns exec n_1 ip link set nginx_in up
ip netns exec n_1 ip link set lo up # почему бы и нет

Если всё корректно настроено, то теперь мы можем пингануть адрес 10.0.0.2:

ping 10.0.0.2

Проделаем все те же действия, но новый пара у нас будет уже между n_1 и n_2:

ip netns exec n_1 ip link add nginx_out_2 type veth peer name nginx_in_2
ip netns exec n_1 ip link set nginx_in_2 netns n_2
ip netns exec n_1 ip addr add 10.0.1.1/24 dev nginx_out_2
ip netns exec n_2 ip addr add 10.0.1.2/24 dev nginx_in_2
ip netns exec n_1 ip link set nginx_out_2 up
ip netns exec n_2 ip link set nginx_in_2 up
ip netns exec n_2 ip link set lo up

Если всё получилось корректно, то должен теперь из n_1 пинговаться 10.0.1.2:

ip netns exec n_1 ping 10.0.1.2

Ура! С настройкой сети мы закончили. 

Последний штрих, создание shell скриптов для запуска наших контейнеров:

В файле /srv/container/start_1.sh
#!/bin/bash

mount --bind ./container1/var/log/nginx ./arch-fs/var/log/nginx
mount --bind ./container1/etc/nginx ./arch-fs/etc/nginx

chroot ./arch-fs /sbin/nginx -g 'daemon off;'

И в файле /srv/container/start_2.sh
#!/bin/bash

mount --bind ./container2/var/log/nginx ./arch-fs/var/log/nginx
mount --bind ./container2/var/www/html ./arch-fs/var/www/html
mount --bind ./container2/etc/nginx ./arch-fs/etc/nginx

chroot ./arch-fs /sbin/nginx -g 'daemon off;'

Готово! Осталось это всё запустить:

ip netns exec n_2 unshare -m -i -p -u -f --mount-proc ./start2.sh &
ip netns exec n_1 unshare -m -i -p -u -f --mount-proc ./start1.sh &

И теперь если мы попробуем отправить http запрос по адресу 10.0.0.2:80/ то должны получить содержимое файла index.html, т.е. Hello friend!

curl http://10.0.0.2:80/
Hello friend!

Фух, это было утомительно. Однако у нас получилось запустить 2 ведь сервера в раздельных контейнерах без докера. А ведь с использованием докера это всё бы заняло считанные минуты!
Replies: >>7
>>6 (OP) 
[New Reply]
1 reply | 0 files
Connecting...
- news - rules -