Постановки задачи:
Имеется статический веб-сайт, никакой динамики, максимум js. Необходимо создать из него Docker-образ, затем загрузить его на Production-сервер и подключить SSL.
Вводные:
На сервере уже имеется рабочий nginx для других не-Docker сайтов.
В данной статье мы рассмотрим подключение сайта к субдомену (домен третьего уровня). Домен делегирован на Cloudflare. Да, там есть pages и он прекрасно справляется с serve статических сайтов, но данная статья описывает путь именно через Docker.
Начал изучать Docker и решил написать данную заметку, возможно пригодится в освоении другим специалистам.
- Добавляем A-запись, в данном случае endocker.endlessnights.ru, который будет смотреть на 185.255.132.54 .
- Создаем в каталоге проекта рядом с index.html файл Dockerfile со следующим содержимым:
FROM nginx
COPY ./ /data/www/ # копируем всё содержимое сайта в /data/www/
COPY ensite.conf /etc/nginx/conf.d/ensite.conf # копируем файл конфигурации nginx сайта
COPY nginx.conf /etc/nginx/nginx.conf # копируем файл конфигурации nginx по шаблону
Создаем файл конфигурации сайта endocker.conf:
server {
listen 80;
server_name localhost;
location / {
root /data/www;
index index.html;
}
}
Создаем конфигурационный файл для nginx по шаблону + + инклюдим ссылку на файл конфигурации nginx сайта:
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/ensite.conf;
}
Docker у меня работает на MBA M1 (arm), а сервер в облаке на linux, поэтому нам нужно изменить целевую платформу для Docker-образа на linux/amd64, для этого будем использовать Docker buildx:
docker buildx create --use
docker buildx build --platform linux/amd64,linux/arm64 --push -t legeminus/en2 # legeminus/en2 - тег
В таком случае Docker-образ сразу запушится в Docker Hub.
После успешной сборки заходим на наш облачный сервер и загружаем наш образ для его дальнейшего запуска (Я использую TMUX, так как это учебная практика, но на production лучше воспользоваться Systemd):
docker pull legeminus/en3
docker run -p 800:80 legeminus/en3
Тут 80 порт в контейнере будем слушать 800 порт снаружи, то есть site:800 > docker.site:80 грубо говоря.
Готовим nginx на стороне Linux-сервера.
Данный сервис у меня уже запущен и поэтому запуск двух биндов на 80 порту невозможен.
Идем в /etc/nginx/sites-available/ и создаем новый файл без расширения endocker :
server {
listen 80;
server_name endocker.endlessnights.ru;
location / {
proxy_pass http://127.0.01:800;
}
Создаем символическую ссылку:
sudo ln -s /etc/nginx/sites-available/endocker /etc/nginx/sites-enabled/
Также, проверяем, что файл конфигурации nginx корректен и перезапускаем nginx:
sudo nginx -t
sudo service nginx restart
Наконец запускаем certbot для получения SSL:
certbot
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator nginx, Installer nginx
Which names would you like to activate HTTPS for?
Выбираем наше доменное имя, которое указывали во "внешнем" конфигурационном файле nginx нашего проекта, в данном случае endocker.endlessnights.ru .
Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
Здесь выбираем цифру 2, чтобы все запросы на http редиректились на https.
Итоговый результат файл конфигурации nginx endocker.nginx:
server_name endocker.endlessnights.ru;
location / {
proxy_pass http://127.0.01:800;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/endocker.endlessnights.ru/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/endocker.endlessnights.ru/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}server {
if ($host = endocker.endlessnights.ru) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name endocker.endlessnights.ru;
return 404; # managed by Certbot
По итогу схема грубо говоря выглядит так:
docker.localhost:80 > localhost:800 + nginx (800>80>443) =example.com:443 (редирект с 80 на 443)
Сайт из Docker-контейнере размещен тут: https://endocker.endlessnights.ru
Основной сайт с идентичным содержимым тут: https://endlessnights.ru , только он на Cloudlfare Pages.
Можно полагать, что, если отсутствуют запущенный имеющийся nginx на сервере Linux, всё сервить можно и внутри Docker-контейнера.
Плюсанул в карму. Хабр торт!
Спасибо за статью, так держать! Но это решение для решенных еще вчера вопросов. Прокси уже несколько лет как не лежат в контейнере, и вынесены в другие слои выше, а докер сегодня это про скучную установку зависимостей, копирование файла и запуск скрипта/бинаря. Давайте про кубернетисы лучше!
Привет! Погляди https://github.com/TopTuK/pmi.landing - кажется, что чутка проще вышло.
Reverse proxy: https://github.com/nginx-proxy/nginx-proxy
Спасибо.
Dockerfile получается доступным для скачивания и прочие конфигурации
мне, кажется, лучше Dockerfile вытащить на уровень выше и папку с конфигами отдельно
Еще бы неплохо добавить файл .dockerignore чтобы при сборке в образ не попали лишние файлы (например директория .git).