Один из сотни способов публикации нескольких production проектов на одном сервере

в 14:32, , рубрики: devops, docker nginx-proxy

image
Когда сайтов становится чуть больше чем один, а ресурсов одного сервера хватает с лихвой, встает вопрос как не переплачивать и упаковать все в одну виртуальную машину самого привлекательного сервиса, с учетом того, что когда-нибудь наши приложения разрастутся в масштабную распределенную сеть — мы обязаны заложить зернышко highload.

Описанное ниже скорее будет полезно тем, кто только начинает идти уверенными шагами в своем ремесле.

Из превьюшки видно, всю текущую архитектуру, она довольна проста, в основе лежит docker, который включает в себя

  • Nginx контейнер который смотрит во вне и проксирует все запросы
  • Много-много наших приложений, соответственно заключенных в контейнеры
  • Управление всем процессом

Настроим окружение

apt update
apt install docker.io
mkdir /home/app

Давайте развернем наши приложения

Добавлю небольшую помарочку, для тех кто еще мало знаком с docker, все контейнеры приложений будут запущены без доступа ко внешней среде, это очень удобно — сильно увеличивает безопасность, доступ к ним будет осуществляться только путем проксирования трафика через nginx. Вы также можете запустить для своих нужд отдельные хосты, например с MariaDB или Mongo и получить к ним доступ по локальному IP.

Первое будет на nodejs с подключенным ssl

mkdir /home/app/web-one.oyeooo.com
mkdir /home/app/web-one.oyeooo.com/ssl
nano index.js
nano package.json

index.js
const fs = require("fs"),
    https = require("https"),
    express = require("express"),
    app = express(),
    port = 443

let options = {
    key: fs.readFileSync("ssl/web-one.oyeooo.com.key"),
    cert: fs.readFileSync("ssl/web-one.oyeooo.com.crt")
},
app = express()

https.createServer(options, app).listen(port, function(){
  console.log("Express server listening on port " + port);
})

app.get("/", function (req, res) {
    res.writeHead(200)
    res.end("Oyeooo")
})

package.json

{
  "name": "oyeooo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "directories": {
    "lib": "lib"
  },
  "scripts": {
    "start": "node index.js"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.17.1"
  }
}

Получаем SLL и кладем сертификаты в папку /home/app/web-one.oyeooo.com/ssl

Второе будет простое apache static приложение

mkdir /home/app/web-two.oyeooo.com
mkdir /home/app/web-two.oyeooo.com
nano index.html

index.html

<!DOCTYPE html>
<html>
    <head>
        <title>Welcome to me!</title>
    </head>
    <body>
        <h1>Oyeooo!</h1>
        <p><em>Thank you for using habr.</em></p>
    </body>
</html>

Теперь запускаем контейнеры

sudo docker run --name web-one -v /home/app/web-one.oyeooo.com:/home/app -it node bash
cd /home/app
npm i
npm start

ctrl + q + p

sudo docker run --name web-two -d -v /home/app/web-two.oyeooo.com:/usr/local/apache2/htdocs httpd
cd /home/app
npm i
npm start

ctrl + q + p

Получаем ip наших контейнеров

docker inspect web-one
docker inspect web-two

В обоих случаях нам нужно получить IPAddress

                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:0a",
                    "DriverOpts": null
                }
            }
        }
    }
]

Переходим к nginx-proxy

mkdir /home/app/nginx
mkdir /home/app/nginx/conf
mkdir /home/app/nginx/ssl
mkdir /home/app/nginx/logs

Создаем два conf для наших сайтов:

web-one.oyeooo.com.conf

server {
listen 80;
server_name web-one.oyeooo.com;
access_log /var/log/nginx/web-one.oyeooo.com/http-access.log;
error_log /var/log/nginx/web-one.oyeooo.com/http-error.log;
return 301 https://$host$request_uri;
}

server {
listen 443 ssl;
server_name web-one.oyeooo.com.conf;
access_log /var/log/nginx/web-one.oyeooo.com/https-access.log;
error_log /var/log/nginx/web-one.oyeooo.com/https-error.log;
ssl_certificate /etc/nginx/ssl/web-one.oyeooo.com/web-one.oyeooo.com.crt;
ssl_certificate_key /etc/nginx/ssl/web-one.oyeooo.com/web-one.oyeooo.com.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

location / {
proxy_pass https://172.17.0.2/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;

client_max_body_size 512M;
}

}

web-two.oyeooo.com.conf

server {
listen 80;
server_name web-one.oyeooo.com;
access_log /var/log/nginx/web-one.oyeooo.com/http-access.log;
error_log /var/log/nginx/web-one.oyeooo.com/http-error.log;

location / {
proxy_pass http://172.17.0.3/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;

client_max_body_size 512M;
}

}

Разворачиваем nginx:

sudo docker run --name nginx -it -v /home/app/nginx/logs:/var/log/nginx -v /home/app/nginx/ssl:/etc/nginx/ssl -v /home/app/nginx/conf:/etc/nginx/conf.d nginx bash
#Проверим присутствуют ли наши conf и ssl
ls /etc/nginx/conf.d
ls /etc/nginx/ssl
#Запускаем nginx
service nginx start
nginx -s reload

Окружение развернуто. Спасибо!

Регулировать наши маршруты можно файлами conf — создаем или удаляем и перезагружаем:

docker exec -it nginx nginx -s reload

В случае успеха получим:

2019/06/18 13:26:47 [notice] 475#475: signal process started

Если статья выйдет из песочницы — напишу crm для управления логикой.

Автор: oyeooo

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js