For Docker based Angular application I want to enable Brotli compression on Nginx for this I have added below commands to Dockerfile
and turned brotli on in nginx/default.conf
file.
nginx/default.conf:
server {
brotli on;
brotli_static on;
listen 80;
root /usr/share/nginx/html;
location / {
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
Dockerfile:
FROM node:16-alpine as build-env
WORKDIR /app
ADD package.json .
RUN npm install
ADD . .
RUN npm run build:prod
FROM nginx:alpine
RUN apk add nginx-mod-http-brotli
RUN sed -i '1i load_module /usr/lib/nginx/modules/ngx_http_brotli_filter_module.so;' /etc/nginx/nginx.conf
RUN sed -i '1i load_module /usr/lib/nginx/modules/ngx_http_brotli_static_module.so;' /etc/nginx/nginx.conf
COPY --from=build-env /app/dist/ng-docker-mark-2 /usr/share/nginx/html
COPY nginx/default.conf /etc/nginx/conf.d/default.conf
EXPOSE 8080
Here, I have added nginx:alpine
after that installing nginx-mod-http-brotli
which is an Apline Linux Package nginx-mod-http-brotli. Later adding load_module
on top of /etc/nginx/nginx.conf
file.
Now, the build command runs without any error:
docker build -t ng-docker:mark-3 .
But when I try to create and run the container get below error:
docker run -p 4300:80 --name ng-docker-mark-3-container-1 ng-docker:mark-3
Error:
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: /etc/nginx/conf.d/default.conf differs from the packaged version
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2023/05/12 14:34:22 [emerg] 1#1: module "/usr/lib/nginx/modules/ngx_http_brotli_static_module.so" version 1022001 instead of 1023004 in /etc/nginx/nginx.conf:1
nginx: [emerg] module "/usr/lib/nginx/modules/ngx_http_brotli_static_module.so" version 1022001 instead of 1023004 in /etc/nginx/nginx.conf:1
Mainly it talks about this:
version 1022001 instead of 1023004
I have checked the container through Windows Docker Desktop app and I can see the modules got installed correctly, and its appearing in world
file:
/etc/apk/world:
alpine-baselayout
alpine-keys
apk-tools
busybox
ca-certificates
curl
libc-utils
libintl
musl
nginx=1.23.4-r1
nginx-mod-http-brotli
nginx-module-geoip=1.23.4-r1
nginx-module-image-filter=1.23.4-r1
nginx-module-njs=1.23.4.0.7.11-r1
nginx-module-xslt=1.23.4-r1
tzdata
Also, modules are appearing in the /usr/lib/nginx/modules
folder too:
What I tried already:
load_module
syntax from top of the
/etc/nginx/nginx.conf
file then it gives error on brotli on
this
line of nginx/default.conf
file.apt
approach where I have used the nginx:latest
distribution but there I got package not found issue.Struggled with this too. It is a mismatch between the compiled version of nginx and the module. The answer is to fetch them from the same source. So instead of using nginx:alpine
, just use alpine
# Build container
FROM node:18-alpine AS builder
# Make sure we got brotli
RUN apk update
RUN apk add --upgrade brotli
WORKDIR /usr
COPY package*.json ./
COPY src ./src
COPY public ./public
RUN npm install
RUN npm run build
RUN cd /usr/dist && find . -type f -exec brotli {} \;
# Actual runtime container
FROM alpine
RUN apk add brotli nginx nginx-mod-http-brotli
# Minimal config
COPY nginx/default.conf /etc/nginx/http.d/default.conf
# Actual data
COPY --from=builder /usr/dist /usr/share/nginx/html
CMD ["nginx", "-g", "daemon off;"]
EXPOSE 80
Note: I only use brotli static since I created .br
files in the build step.
access_log /dev/stdout;
error_log /dev/stdout info;
server {
brotli_static on;
listen 80 default_server;
listen [::]:80 default_server;
# Everything is a 404
root /usr/share/nginx/html;
location / {
try_files $uri $uri/ =404;
}
# You may need this to prevent return 404 recursion.
location = /404.html {
internal;
}
}
You might want to play with more nginx settings.