How To Dockerize A Bun App🐳
Tags: docker, devops, webdev, javascript
Published: 2023-09-25 10:20:31

Dockerizing your Bun app is a breeze with this super minimal Dockerfile. Follow me on the journey to make it production-ready! 🐳🚀

```Dockerfile
FROM oven/bun
COPY . .
RUN bun install
CMD ["bun", "index.ts"]
```

Make sure to change `index.ts` to your entry point and then build it like this:
```bash
docker build -t bun-minimal .
```

## Improvements 

As always with Docker, you can improve your Docker image in a few easy ways. Let's look at the two most obvious ways, copying only what you need (improving caching!) and multi-stage builds (improving the image size!) 🚀

### Copying only what you need

A lot of the time that your docker build takes comes from expensive I/O operations or the inability to cache single steps of your build process.


#### `.dockerignore` 🤷

Firstly, create a `.dockerignore` file with everything that you do not want in your Docker image. This usually includes stuff like your `node_modules`, compiled files, or documentation. Simply write the folder names that you want to be ignored in a file, or copy an [existing one](https://github.com/RisingStack/kubernetes-nodejs-example/blob/master/.dockerignore).

```plain
node_modules
README.md
LICENSE
```

#### Separate Copy Steps

If you are actively developing your app and you need to constantly rebuild your Docker Image, chances are that your code changes a lot more than your dependencies. You can profit from that fact by separating the install and build steps. Docker will then only re-install your dependencies if they actually changed! 🥳

```Dockerfile
FROM oven/bun

# Copy the lock and package file
COPY bun.lockb . 
COPY package.json . 

# Install dependencies
RUN bun install --frozen-lockfile

# Copy your source code
# If only files in the src folder changed, this is the only step that gets executed!
COPY src ./src 

CMD ["bun", "index.ts"]
```


### Multi-Stage Builds


If you want to be a bit fancier or you need a smaller Docker image, you can also use bun to [bundle an executable.
](https://bun.sh/docs/bundler/executables) This will compile your code to a standalone binary that includes the Bun runtime. You can then create a [multi-stage build](https://docs.docker.com/build/building/multi-stage/), reducing your image size by around **35%**

We take the Dockerfile from the previous step as the template but extend it by not using bun run, but bun build. We then copy the compiled binary and create a new Ubuntu image that only includes this binary. This simple step reduces our build size by **88 Megabyte!** 🤯

```Dockerfile
FROM oven/bun AS build # tag it as build

WORKDIR /app

COPY bun.lockb .
COPY package.json .

RUN bun install --frozen-lockfile

COPY src ./src

# compile everything to a binary called cli which includes the bun runtime
RUN bun build ./src/index.ts --compile --outfile cli

FROM ubuntu:22.04 # use a smaller image without bun

WORKDIR /app

# copy the compiled binary from the build image
COPY --from=build /app/cli /app/cli

# execute the binary!
CMD ["/app/cli"]
```


## Next Steps

How was your experience developing and deploying Bun? I've really enjoyed it so far, although there is still a lot of work to do to make it truly great. I'd love to hear your opinions!

If you want to go further, check out the next blog post where you learn [how to deploy your dockerized Bun App on Hetzner](https://dev.to/code42cate/deploying-bun-apps-on-hetzner-33kb) with [Sliplane!](https://sliplane.io?utm_source=dockerizebun)