DEV Community

Cover image for How to Dockerize SvelteKit
Jonas Scholz
Jonas Scholz Subscriber

Posted on

How to Dockerize SvelteKit

Hey there! This guide will help you containerize your SvelteKit app, making it easier to deploy and manage. Important Note: this is SvelteKit, not Svelte!:)

Setup

If you don't have a SvelteKit project, you can create one by running:

npx sv create my-svelte-app --template demo --types ts
Enter fullscreen mode Exit fullscreen mode

First, we need to set up SvelteKit to use the adapter-node. This adapter helps build your site for Node.js, which is crucial for containerization.

Start by installing the adapter-node:

npm i -D @sveltejs/adapter-node
Enter fullscreen mode Exit fullscreen mode

Once installed, open your svelte.config.js file and change the adapter to use adapter-node:

// svelte.config.js
- import adapter from '@sveltejs/adapter-auto';
+ import adapter from '@sveltejs/adapter-node';
Enter fullscreen mode Exit fullscreen mode

Now, let's create the Dockerfile. This file tells Docker how to build and run your SvelteKit application. Here's what the Dockerfile might look like:

# Use a Node.js Alpine image for the builder stage
FROM node:22-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
RUN npm prune --production

# Use another Node.js Alpine image for the final stage
FROM node:22-alpine
WORKDIR /app
COPY --from=builder /app/build build/
COPY --from=builder /app/node_modules node_modules/
COPY package.json .
EXPOSE 3000
ENV NODE_ENV=production
CMD [ "node", "build" ]
Enter fullscreen mode Exit fullscreen mode

Let's break down the Dockerfile:

  1. Builder Stage: We start with a Node.js Alpine image, set the working directory to /app, copy the package files, install dependencies, copy the rest of the source files, build the SvelteKit app, and prune dependencies to production-only.

  2. Final Stage: We start fresh with another Alpine Node.js image, copy over the built app, production node_modules, and package.json from the builder stage, expose port 3000, set the environment to production, and specify the command to run the app.

To keep the Docker build context clean and speed up the build process, create a .dockerignore file in your project root:

Dockerfile
.dockerignore
.git
.gitignore
.gitattributes
README.md
.npmrc
.prettierrc
.eslintrc.cjs
.graphqlrc
.editorconfig
.svelte-kit
.vscode
node_modules
build
package
**/.env
Enter fullscreen mode Exit fullscreen mode

Using a multi-stage build helps keep the final image small by discarding unnecessary files and tools after the build process. It also speeds up builds by leveraging Docker's layer caching.

When using adapter-node, you should generally install all dependencies as devDependencies. This allows SvelteKit to bundle them into your app and discard any unused imports. Install new packages with the -D flag, like npm i -D lucide-svelte, whether they're for client-side or server-side use.

However, if you encounter issues like __dirname is not defined during the build, you might need to install the dependency as a regular dependency. This means SvelteKit won't bundle it, and it will be loaded from node_modules at runtime.

If all your dependencies are devDependencies, you can skip copying node_modules in the final stage of the Dockerfile, further reducing the image size.

To build your Docker image, run the following command from the directory containing your Dockerfile:

docker build -t my-sveltekit-app .
Enter fullscreen mode Exit fullscreen mode

Once the build is complete, you can run your containerized app with:

docker run -p 3000:3000 my-sveltekit-app
Enter fullscreen mode Exit fullscreen mode

You can now access your SvelteKit app by navigating to http://localhost:3000 in your web browser.

Dockerized SvelteKit

Handling environment variables in Docker is important. SvelteKit provides four ways to import environment variables, each with different implications for Docker:

  1. $env/dynamic/private: These are runtime variables that don't need to be defined at build time. You can set them in the Dockerfile, pass them when running the container, or use a .env file.

  2. $env/dynamic/public: Similar to dynamic private variables but exposed to the client. They should start with PUBLIC_.

  3. $env/static/private: These are build-time variables that get baked into your Docker image. Use build arguments in your Dockerfile and pass them during the build process.

  4. $env/static/public: Similar to static private variables but exposed to the client. Useful for static builds with adapter-static.

When deploying your app, remember that different platforms handle build-time and runtime environment variables differently. Always refer to the platform's documentation.

Lastly, when using form actions or other server-side features in Docker, you need to set the ORIGIN environment variable correctly to avoid cross-site POST form submission errors. For example:

docker run -p 3000:3000 -e ORIGIN=http://localhost:3000 my-sveltekit-app
Enter fullscreen mode Exit fullscreen mode

In production, replace http://localhost:3000 with your actual domain.

Production Tips

  1. Health Checks: Add a /health endpoint to your app and use Docker's HEALTHCHECK instruction to monitor container health:
HEALTHCHECK --interval=30s --timeout=3s \
  CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1
Enter fullscreen mode Exit fullscreen mode
  1. Memory Limits: Set Node.js memory limits to prevent container crashes:
docker run -p 3000:3000 -e NODE_OPTIONS="--max-old-space-size=512" my-sveltekit-app
Enter fullscreen mode Exit fullscreen mode
  1. Security Scanning: Regularly scan your container for vulnerabilities:
docker scout quickview
Enter fullscreen mode Exit fullscreen mode

Conclusion

That's it! You now have a dockerized SvelteKit application that's optimized for production. If you want to deploy your SvelteKit app, check out sliplane.io

Top comments (2)

Collapse
 
winston0410 profile image
John Winston

Hi Jonas thank you for your article on dockerizing SvelteKit with node adapter. I have written a guide on building production grade docker image for SvelteKit with static adapter, hopefully you will find that interesting.

Collapse
 
code42cate profile image
Jonas Scholz

Really well written post!