diff --git a/docker-compose.yml b/docker-compose.yml index 508567fa..8faba6f3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,6 +10,8 @@ services: - "${FRONTEND_PORT_HTTPS}:443" networks: - shuffle + environment: + - BACKEND_HOSTNAME=${BACKEND_HOSTNAME} restart: unless-stopped depends_on: - backend diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 2c937de4..c0d93924 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -8,12 +8,17 @@ COPY package.json /usr/src/app/package.json RUN npm install --verbose -COPY . /usr/src/app +# copy only required files to not trigger rebuilding every time +COPY ./certs /usr/src/app/certs/ +COPY ./public /usr/src/app/public/ +COPY ./src /usr/src/app/src/ +COPY ./*.sh /usr/src/app/ +COPY ./*.json /usr/src/app/ RUN npm run-script build # Production environment -from nginx:latest +FROM nginx:latest RUN mkdir -p /usr/share/nginx/html/build RUN mkdir -p /usr/share/nginx/html/css @@ -26,8 +31,16 @@ COPY --from=builder /usr/src/app/build /usr/share/nginx/html COPY --from=builder /usr/src/app/certs/fullchain.pem /etc/nginx/fullchain.cert.pem COPY --from=builder /usr/src/app/certs/privkey.pem /etc/nginx/privkey.pem -# Prod -COPY --from=builder /usr/src/app/nginx.conf /etc/nginx/nginx.conf +# install CONFD +ENV CONFD_VERSION 0.16.0 +RUN curl -sSL https://github.com/kelseyhightower/confd/releases/download/v${CONFD_VERSION}/confd-${CONFD_VERSION}-linux-amd64 -o /usr/local/bin/confd && \ + chmod +x /usr/local/bin/confd +COPY ./confd /etc/confd + +# rewrite command & entrypoint with ours +COPY ./entrypoint.sh / +ENTRYPOINT [ "/entrypoint.sh" ] +CMD ["nginx", "-g", "daemon off;"] EXPOSE 80 EXPOSE 443 diff --git a/frontend/confd/conf.d/nginx.conf.toml b/frontend/confd/conf.d/nginx.conf.toml new file mode 100644 index 00000000..0c6498de --- /dev/null +++ b/frontend/confd/conf.d/nginx.conf.toml @@ -0,0 +1,9 @@ +[template] +src = "nginx.conf" +dest = "/etc/nginx/nginx.conf" +uid = 0 +gid = 0 +mode = "0644" +keys = [ + "/", +] diff --git a/frontend/confd/templates/nginx.conf b/frontend/confd/templates/nginx.conf new file mode 100644 index 00000000..6b61364a --- /dev/null +++ b/frontend/confd/templates/nginx.conf @@ -0,0 +1,103 @@ +user nobody nogroup; +worker_processes auto; # auto-detect number of logical CPU cores + +events { + worker_connections 512; # set the max number of simultaneous connections (per worker process) +} + +http { + client_max_body_size 250M; + + include mime.types; + + # thanks stackoverflow http://stackoverflow.com/a/5132440/2406040 + gzip on; + gzip_http_version 1.1; + gzip_vary on; + gzip_comp_level 6; + gzip_proxied any; + gzip_types text/plain text/css application/json application/javascript application/x-javascript text/javascript text/xml application/xml application/rss+xml application/atom+xml application/rdf+xml; + + # make sure gzip does not lose large gzipped js or css files + # see http://blog.leetsoft.com/2007/07/25/nginx-gzip-ssl.html + gzip_buffers 16 8k; + + # Disable gzip for certain browsers. + gzip_disable "MSIE [1-6].(?!.*SV1)"; + + server { + listen 80; + server_name "localhost"; + location / { + # avoid clickjacking + add_header X-Frame-Options DENY; + # block MIME sniffing + add_header X-Content-Type-Options nosniff; + + # security headers + add_header X-XSS-Protection "1; mode=block"; + # add_header Content-Security-Policy "default-src 'self'"; + add_header Referrer-Policy "no-referrer"; + server_tokens off; + + root /usr/share/nginx/html; + gzip_static on; + expires 1y; + add_header Cache-Control public; + add_header ETag ""; + try_files $uri /index.html; + } + + location /api/v1 { + proxy_pass http://{{ getenv "BACKEND_HOSTNAME" "shuffle-backend" }}:5001; + proxy_buffering off; + proxy_http_version 1.1; + + proxy_connect_timeout 900; + proxy_send_timeout 900; + proxy_read_timeout 900; + send_timeout 900; + } + } + + server { + listen 443 ssl; + server_name "localhost"; + ssl_certificate fullchain.cert.pem; + ssl_certificate_key privkey.pem; + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_ciphers HIGH:!aNULL:!MD5; + + location / { + # avoid clickjacking + add_header X-Frame-Options DENY; + # block MIME sniffing + add_header X-Content-Type-Options nosniff; + + # security headers + add_header X-XSS-Protection "1; mode=block"; + # add_header Content-Security-Policy "default-src 'self'"; + add_header Referrer-Policy "no-referrer"; + server_tokens off; + + root /usr/share/nginx/html; + gzip_static on; + expires 1y; + add_header Cache-Control public; + add_header ETag ""; + try_files $uri /index.html; + } + + # Get the hostname from environment here? + location /api/v1 { + proxy_pass http://{{ getenv "BACKEND_HOSTNAME" "shuffle-backend" }}:5001; + proxy_buffering off; + proxy_http_version 1.1; + + proxy_connect_timeout 900; + proxy_send_timeout 900; + proxy_read_timeout 900; + send_timeout 900; + } + } +} diff --git a/frontend/entrypoint.sh b/frontend/entrypoint.sh new file mode 100755 index 00000000..09be2558 --- /dev/null +++ b/frontend/entrypoint.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +# generate configs +/usr/local/bin/confd -backend="env" -confdir="/etc/confd" -onetime + +# run main command +exec "$@" diff --git a/frontend/nginx.conf b/frontend/nginx.conf deleted file mode 100644 index 59405dca..00000000 --- a/frontend/nginx.conf +++ /dev/null @@ -1,89 +0,0 @@ -user nobody nogroup; -worker_processes auto; # auto-detect number of logical CPU cores - -events { - worker_connections 512; # set the max number of simultaneous connections (per worker process) -} - -http { - client_max_body_size 250M; - - include mime.types; - - # thanks stackoverflow http://stackoverflow.com/a/5132440/2406040 - gzip on; - gzip_http_version 1.1; - gzip_vary on; - gzip_comp_level 6; - gzip_proxied any; - gzip_types text/plain text/css application/json application/javascript application/x-javascript text/javascript text/xml application/xml application/rss+xml application/atom+xml application/rdf+xml; - - # make sure gzip does not lose large gzipped js or css files - # see http://blog.leetsoft.com/2007/07/25/nginx-gzip-ssl.html - gzip_buffers 16 8k; - - # Disable gzip for certain browsers. - gzip_disable “MSIE [1-6].(?!.*SV1)”; - - server { - listen 80; - server_name "localhost"; - location / { - # avoid clickjacking - add_header X-Frame-Options DENY; - # block MIME sniffing - add_header X-Content-Type-Options nosniff; - - # security headers - add_header X-XSS-Protection "1; mode=block"; - # add_header Content-Security-Policy "default-src 'self'"; - add_header Referrer-Policy "no-referrer"; - server_tokens off; - - root /usr/share/nginx/html; - gzip_static on; - expires 1y; - add_header Cache-Control public; - add_header ETag ""; - try_files $uri /index.html; - } - - location /api/v1 { - proxy_pass http://shuffle-backend:5001; - } - } - - server { - listen 443 ssl; - server_name "localhost"; - ssl_certificate fullchain.cert.pem; - ssl_certificate_key privkey.pem; - ssl_protocols TLSv1 TLSv1.1 TLSv1.2; - ssl_ciphers HIGH:!aNULL:!MD5; - - location / { - # avoid clickjacking - add_header X-Frame-Options DENY; - # block MIME sniffing - add_header X-Content-Type-Options nosniff; - - # security headers - add_header X-XSS-Protection "1; mode=block"; - # add_header Content-Security-Policy "default-src 'self'"; - add_header Referrer-Policy "no-referrer"; - server_tokens off; - - root /usr/share/nginx/html; - gzip_static on; - expires 1y; - add_header Cache-Control public; - add_header ETag ""; - try_files $uri /index.html; - } - - # Get the hostname from environment here? - location /api/v1 { - proxy_pass http://shuffle-backend:5001; - } - } -}