Taking it to Production: How to Dockerize and Deploy a Bun App on Coolify 🚀
Welcome back fellows! Over the last few articles, we stripped away the bloated tools of the traditional Node.js era, reclaimed our developer experience, and built a blazing-fast API using Bun and Elysia.js. But an API sitting on your localhost does not do anyone much good.
It is time to push this code to production. If you have been following the blog, you already know that we are huge fans of self-hosting to ditch expensive managed hosting bills. Today, we are going to containerize our new Bun application and deploy it to our DigitalOcean droplet using Coolify.
1. Writing the Optimized Bun Dockerfile
While Coolify can automatically attempt to build your app using Nixpacks, writing your own Dockerfile gives you complete control and ensures you are taking full advantage of Bun's native speed. We are going to use a multi-stage build. This means we use one stage to install our dependencies and another to run the final app, keeping the final container incredibly small and secure.
Create a file named Dockerfile in the root of your Elysia project:
Dockerfile
# Stage 1: Setup base image
FROM oven/bun:latest AS base
WORKDIR /app
# Stage 2: Install dependencies
FROM base AS builder
COPY package.json bun.lockb ./
RUN bun install --frozen-lockfile
# Stage 3: Copy source code
COPY src ./src
# Stage 4: Production release
FROM base AS release
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/src ./src
COPY package.json ./
# Expose the port Elysia runs on
EXPOSE 3000
# Run the application natively without transpilation
CMD ["bun", "run", "src/index.ts"]
This multi-stage approach ensures your production image is lightweight and completely free of unnecessary build tools.
2. Deploying via Coolify
Because Coolify handles the underlying Docker operations, you don't need to manually SSH into your server to run pull commands. You manage everything—databases, applications, environment variables, and domains—from a slick web dashboard.
Here is how to get your new container running:
- Connect Your Repository: Open your Coolify setup screen and link your GitHub or GitLab repository containing your new Bun code.
- Select the Build Pack: By default, Coolify might try to use Nixpacks. In your application settings, change the Build Pack option to Dockerfile. This tells Coolify to use the custom multi-stage file we just created.
- Configure the Port: Coolify needs to know where to route traffic. Ensure the deployment port is set to
3000(or whichever port you specified in your Elysia app). - Deploy: Click the Deploy button. Coolify will automatically pull the newest image from Docker Hub (or build your source code), stop your outdated container, and spin up the new one.
3. The Power of Self-Hosting
Just like that, your ultra-fast Bun application is live on the internet! By combining Bun's lightweight runtime with a minimalist Dockerfile and Coolify's automated deployments, you get the exact git push workflow popularized by Heroku, but with a fraction of the CPU overhead and cost.
Self-hosting gives you full control over your infrastructure while keeping costs down!
In Part 5—our final installment—we will dive deep under the hood. We will explore Bun's architecture, look at the Zig programming language, and break down exactly why the APIs we just deployed are running so much faster than Node.js.
Have you ever tried self-hosting your own applications, or do you prefer managed services? Let me know in the comments!