diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..c9d88c76 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,5 @@ +node_modules +.git +.github +*.log +dist diff --git a/.gitignore b/.gitignore index 0784e613..94172457 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ node_modules dist + +# certificates for local development +certs .cache diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c5b5323a..46c9673a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -50,3 +50,17 @@ ## Инструменты - Расширение [Nunjucks Template](https://marketplace.visualstudio.com/items?itemName=eseom.nunjucks-template) для VS Code + +## Упаковка в контейнер + +- Убедитесь, что у вас установлен [Docker](https://www.docker.com/get-started). +- Выполните команду `docker login` (если вы ещё не авторизованы в Docker Hub). +- Убедитесь что вы ходите в github по ssh (вы клонируете URL такого формата git@github.com...). Если ssh не настроен вам [сюда](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/about-ssh) +- Запустике сбоку `./docker.sh build` в корневой папке проекта. +- Если вы хотите локально потестровать контейнер, выполните команду `./docker.sh run-local` в корневой папке проекта. Приложение запустится на порту 8080. +- Eсли у вас есть сертификаты и вы хотите посмотреть на продовую сборку локально + - Убедитесь что ваша операционная система MacOS или Linux. Для Windows, возможно, тоже заработает с WSL + - Сoзайте папку `certs` в корневой папке проекта и скопируйте все сертификаты туда. + - Добавьте в файл `/etc/hosts` строку `127.0.0.1 web-standards.ru`. Не забудьте удалить этy строку позже, иначе вы всегда будете использовать локальную версию приложения. + - Запустите `./docker.sh run-prod` в корневой папке проекта + - Откройте в браузере `https://web-standards.ru`. diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..16302137 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,33 @@ +# syntax=docker/dockerfile:1.6 + +FROM node:lts-alpine AS builder +WORKDIR /app +RUN apk add --no-cache git +COPY package*.json ./ +RUN npm clean-install +COPY . . +RUN npm run build + +FROM alpine AS nginx-config +WORKDIR /nginx +RUN apk add --no-cache git openssh-client +RUN mkdir -p -m 700 /root/.ssh +RUN ssh-keyscan github.com >> /root/.ssh/known_hosts +RUN --mount=type=ssh git clone --depth 1 git@github.com:web-standards-ru/nginx.git . +RUN rm -rf .git + +FROM alpine +ARG NGINX_LOCAL=nginx.local.conf +ARG NGINX_CONF=nginx.conf +RUN apk add --no-cache nginx nginx-mod-http-brotli nginx-mod-http-headers-more brotli-libs openssl +RUN getent group www-data || addgroup -S www-data +RUN getent passwd www-data || adduser -S -G www-data www-data +COPY --from=nginx-config /nginx /etc/nginx +COPY --from=builder /app/dist/ /var/www/web-standards.ru/html +COPY --from=builder /app/${NGINX_CONF} /etc/nginx/conf.d/default.conf +COPY --from=builder /app/${NGINX_LOCAL} /etc/nginx/${NGINX_LOCAL} +RUN sed -i '1aload_module /usr/lib/nginx/modules/ngx_http_brotli_static_module.so;' /etc/nginx/nginx.conf +RUN sed -i '1aload_module /usr/lib/nginx/modules/ngx_http_brotli_filter_module.so;' /etc/nginx/nginx.conf +RUN mkdir -p /etc/ssl/certs && openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048 +EXPOSE 80 +CMD ["nginx","-g","daemon off;"] diff --git a/docker.sh b/docker.sh new file mode 100755 index 00000000..0beae262 --- /dev/null +++ b/docker.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash +set -euo pipefail + +export DOCKER_BUILDKIT=1 + + +if [ -z "$SSH_AUTH_SOCK" ]; then + echo "❌ SSH agent not available. Run 'ssh-agent' and 'ssh-add' first." + exit 1 +fi + + +task="${1:-}" +certs_dir="${2:-./certs}" + +case "$task" in + build) + docker buildx build --ssh default -t webstandards_ru --build-arg 'NGINX_CONF=nginx.conf' --build-arg 'NGINX_LOCAL_CONF=nginx.local.conf' . + ;; + run-local) + docker run --rm -p 8080:80 webstandards_ru nginx -g 'daemon off;' -c /etc/nginx/nginx.local.conf + ;; + run-prod) + [ -n "$certs_dir" ] || { printf "Нет сертификатов. Проверьте папку $certs_dir\n" >&2; exit 1; } + docker run --rm \ + -v "$certs_dir":/etc/letsencrypt/live/web-standards.ru:ro \ + -p 80:80 \ + -p 443:443 \ + webstandards_ru + ;; + debug) + docker run --rm -it -p 8080:80 webstandards_ru sh + ;; + *) + printf "Неправильная команда, должно быть что-то из этого: %s {build|run-local|run-prod}\n" "$(basename "$0")" >&2 + exit 1 + ;; +esac diff --git a/nginx.local.conf b/nginx.local.conf new file mode 100644 index 00000000..94dbeeac --- /dev/null +++ b/nginx.local.conf @@ -0,0 +1,28 @@ +events { + worker_connections 1024; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + sendfile on; + #tcp_nopush on; + + keepalive_timeout 65; + + server { + listen 80; + listen [::]:80; + server_name localhost www.localhost; + + root /var/www/web-standards.ru/html; + index index.html index.xml; + + error_page 404 /404/; + + location ~ /podcast/(cover\.png|feed|episodes/\d+\.mp3) { + root /var/www/web-standards.ru; + } + } +}