Dockerize a Svelte App with routing

Learn how to make routing work in a dockerized Svelte App with an NGINX.

Recently I have started to play around with Svelte as a frontend technology and I have to say I really like it and for me personally it is better than React and Angular.

To deploy my demo app I have decided to containerize it with Docker, even though Docker is not free anymore for companies bigger than 10 people. No problem for me right now, but I am still not happy about this decision by Docker (I understand it from a business perspective though) and there are multiple alternatives that can be tried like Buildah.

To building a containerized application for Docker I have used the following guide, which works like a charm: https://sveltesociety.dev/recipes/publishing-and-deploying/dockerize-a-svelte-app

Routing on NGINX for Svelte apps

One thing I have realized though, if you are using routing in your Svelte app (e.g. with svelte-routing) then this is not working because for Svelte you need to have all requests coming to your index.html in order to get the routing done.

For an NGINX this can be achieved by adding try_files to your config file:

try_files $uri $uri/ /index.html;

NGINX config for Svelte routing

So all you need to do is to create a default.conf with this configuration and update it during the docker build phase. I have create a folder called nginx with the following default.conf:

server {
    listen       80;
    listen  [::]:80;
    server_name  localhost;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
        try_files $uri $uri/ /index.html;
    }

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

Dockerfile to make the Svelte routing work on NGINX

The updated dockerfile looks like this:

FROM node:14 AS build

WORKDIR /app

COPY package.json ./
COPY package-lock.json ./
RUN npm install
COPY . ./
RUN npm run build

FROM nginx:1.23-alpine
COPY --from=build /app/public /usr/share/nginx/html
COPY ./nginx/default.conf /etc/nginx/conf.d/default.conf

That's it, now you can run the docker build command, and the routing is working:

docker build . -t my-image-name