diff --git a/backend/.dockerignore b/backend/.dockerignore index e1347bbf..51276496 100644 --- a/backend/.dockerignore +++ b/backend/.dockerignore @@ -6,5 +6,6 @@ **/.env **/junitxml/ **/staticfiles/ +**/media/ **/venv/ **/__pycache__/ diff --git a/backend/Dockerfile.prod b/backend/Dockerfile.prod index 46b4211d..8756fa99 100644 --- a/backend/Dockerfile.prod +++ b/backend/Dockerfile.prod @@ -8,8 +8,11 @@ WORKDIR /backend ENV PYTHONDONTWRITEBYTECODE 1 ENV PYTHONUNBUFFERED 1 -COPY ./backend/ /backend/ -COPY ./Pipfile* /backend/ +RUN groupadd -g 61000 doccano \ + && useradd -g 61000 -l -M -s /bin/false -u 61000 doccano + +COPY --chown=doccano:doccano ./backend/ /backend/ +COPY --chown=doccano:doccano ./Pipfile* /backend/ # hadolint ignore=DL3013 RUN apt-get update \ @@ -24,6 +27,13 @@ RUN apt-get update \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* -COPY tools/ /opt/bin/ +COPY --chown=doccano:doccano tools/ /opt/bin/ +RUN mkdir -p /backend/staticfiles \ + && chown -R doccano:doccano /backend/staticfiles \ + && mkdir -p /backend/client/dist/static \ + && chown -R doccano:doccano /backend/client/dist/static + +USER doccano:doccano +VOLUME /backend/staticfiles ENTRYPOINT [ "/opt/bin/prod-django.sh" ] diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index ad609882..be8e8979 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -60,7 +60,7 @@ services: - static_volume:/static - media:/media ports: - - 80:80 + - 80:8080 depends_on: - backend networks: diff --git a/nginx/Dockerfile b/nginx/Dockerfile index c7389ed8..6c0b2948 100644 --- a/nginx/Dockerfile +++ b/nginx/Dockerfile @@ -11,6 +11,16 @@ RUN apk add -U --no-cache git python3 make g++ \ FROM nginx:1.17.4-alpine AS runtime -COPY --from=frontend-builder /app/dist /var/www/html -RUN rm /etc/nginx/conf.d/default.conf -COPY nginx/nginx.conf /etc/nginx/conf.d +RUN addgroup -g 61000 doccano \ + && adduser -G doccano -S doccano -u 61000 + +COPY --chown=doccano:doccano --from=frontend-builder /app/dist /var/www/html +COPY nginx/nginx.conf /etc/nginx/nginx.conf +COPY nginx/default.conf /etc/nginx/conf.d/default.conf + +RUN chown -R doccano:doccano /var/cache/nginx \ + && chmod -R g+w /var/cache/nginx + +EXPOSE 8080 + +USER doccano:doccano diff --git a/nginx/default.conf b/nginx/default.conf new file mode 100644 index 00000000..ec65788a --- /dev/null +++ b/nginx/default.conf @@ -0,0 +1,57 @@ +server { + listen 8080; + charset utf-8; + client_max_body_size 100M; + add_header X-Frame-Options DENY; + add_header X-Content-Type-Options nosniff; + add_header X-XSS-Protection "1; mode=block"; + + location / { + root /var/www/html; + try_files $uri /index.html; + } + + location /v1/ { + proxy_pass http://backend:8000/v1/; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $host; + proxy_redirect off; + proxy_read_timeout 300; + } + + location /admin/ { + proxy_pass http://backend:8000/admin/; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $host; + proxy_redirect off; + } + + location = /admin { + absolute_redirect off; + return 301 /admin/; + } + + location /swagger/ { + proxy_pass http://backend:8000/swagger/; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $host; + proxy_redirect off; + } + + location = /swagger { + absolute_redirect off; + return 301 /swagger/; + } + + location /static/ { + autoindex on; + alias /static/; + } + + location /media/ { + autoindex on; + alias /media/; + } +} + +server_tokens off; diff --git a/nginx/nginx.conf b/nginx/nginx.conf index 2f0da887..cb16cc16 100644 --- a/nginx/nginx.conf +++ b/nginx/nginx.conf @@ -1,57 +1,35 @@ -server { - listen 80; - charset utf-8; - client_max_body_size 100M; - add_header X-Frame-Options DENY; - add_header X-Content-Type-Options nosniff; - add_header X-XSS-Protection "1; mode=block"; - - location / { - root /var/www/html; - try_files $uri /index.html; - } - - location /v1/ { - proxy_pass http://backend:8000/v1/; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header Host $host; - proxy_redirect off; - proxy_read_timeout 300; - } - - location /admin/ { - proxy_pass http://backend:8000/admin/; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header Host $host; - proxy_redirect off; - } - - location = /admin { - absolute_redirect off; - return 301 /admin/; - } - - location /swagger/ { - proxy_pass http://backend:8000/swagger/; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header Host $host; - proxy_redirect off; - } - - location = /swagger { - absolute_redirect off; - return 301 /swagger/; - } - - location /static/ { - autoindex on; - alias /static/; - } - - location /media/ { - autoindex on; - alias /media/; - } +worker_processes auto; + +error_log /var/log/nginx/error.log warn; + +# Change pid to allow no super user to run +pid /tmp/nginx.pid; + + +events { + worker_connections 1024; } -server_tokens off; + +http { + proxy_temp_path /tmp/proxy_temp; + client_body_temp_path /tmp/client_temp; + fastcgi_temp_path /tmp/fastcgi_temp; + uwsgi_temp_path /tmp/uwsgi_temp; + scgi_temp_path /tmp/scgi_temp; + + 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; + + keepalive_timeout 65; + + include /etc/nginx/conf.d/*.conf; +} diff --git a/tools/offline_deployment/offline_01_1-optional_use_https.sh b/tools/offline_deployment/offline_01_1-optional_use_https.sh index 468b0edf..3a5a8115 100755 --- a/tools/offline_deployment/offline_01_1-optional_use_https.sh +++ b/tools/offline_deployment/offline_01_1-optional_use_https.sh @@ -14,8 +14,8 @@ openssl req -new -newkey rsa:4096 -sha256 -nodes -x509 -keyout ./nginx/cert.key ssl_cert="/certs/cert.crt" ssl_cert_key="/certs/cert.key" -# edit nginx.conf -sed -i "s|listen 80;|listen 443 ssl;\n ssl_certificate $ssl_cert;\n ssl_certificate_key $ssl_cert_key;|g" nginx/nginx.conf +# edit default.conf +sed -i "s|listen 80;|listen 443 ssl;\n ssl_certificate $ssl_cert;\n ssl_certificate_key $ssl_cert_key;|g" nginx/default.conf # edit nginx Dockerfile echo "RUN mkdir -p /certs/" >> nginx/Dockerfile diff --git a/tools/prod-django.sh b/tools/prod-django.sh index 8c8da596..08867cfc 100755 --- a/tools/prod-django.sh +++ b/tools/prod-django.sh @@ -4,7 +4,6 @@ set -o errexit echo "Making staticfiles" static_dir=staticfiles -mkdir -p client/dist/static if [[ ! -d $static_dir ]] || [[ -z $(ls -A $static_dir) ]]; then echo "Executing collectstatic" python manage.py collectstatic --noinput;