diff options
Diffstat (limited to 'docs/guides')
-rw-r--r-- | docs/guides/ecosystem/docker.md | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/docs/guides/ecosystem/docker.md b/docs/guides/ecosystem/docker.md new file mode 100644 index 000000000..26a1eaccd --- /dev/null +++ b/docs/guides/ecosystem/docker.md @@ -0,0 +1,140 @@ +--- +name: Containerize a Bun application with Docker +--- + +{% callout %} +This guide assumes you already have [Docker Desktop](https://www.docker.com/products/docker-desktop/) installed. +{% /callout %} + +[Docker](https://www.docker.com) is a platform for packaging and running an application as a lightweight, portable _container_ that encapsulates all the necessary dependencies. + +--- + +To _containerize_ our application, we define a `Dockerfile`. This file contains a list of instructions to initialize the container, copy our local project files into it, install dependencies, and starts the application. + +```docker#Dockerfile +# use the official Bun image +# see all versions at https://hub.docker.com/r/oven/bun/tags +FROM oven/bun:1 as base +WORKDIR /usr/src/app + +# install dependencies into temp directory +# this will cache them and speed up future builds +FROM base AS install +RUN mkdir -p /temp/dev +COPY package.json bun.lockb /temp/dev/ +RUN cd /temp/dev && bun install --frozen-lockfile + +# install with --production (exclude devDependencies) +RUN mkdir -p /temp/prod +COPY package.json bun.lockb /temp/prod/ +RUN cd /temp/prod && bun install --frozen-lockfile --production + +# copy node_modules from temp directory +# then copy all (non-ignored) project files into the image +FROM install AS prerelease +COPY --from=install /temp/dev/node_modules node_modules +COPY . . + +# [optional] tests & build +ENV NODE_ENV=production +RUN bun test +RUN bun run build + +# copy production dependencies and source code into final image +FROM base AS release +COPY --from=install /temp/prod/node_modules node_modules +COPY --from=prerelease /usr/src/app/index.ts . +COPY --from=prerelease /usr/src/app/package.json . + +# run the app +USER bun +EXPOSE 3000/tcp +ENTRYPOINT [ "bun", "run", "index.ts" ] +``` + +--- + +Now that you have your docker image, let's look at `.dockerignore` which has the same syntax as `.gitignore`, here you need to specify the files/directories that must not go in any stage of the docker build. An example for a ignore file is + +```txt#.dockerignore +node_modules +Dockerfile* +docker-compose* +.dockerignore +.git +.gitignore +README.md +LICENSE +.vscode +Makefile +helm-charts +.env +.editorconfig +.idea +coverage* +``` + +--- + +We'll now use `docker build` to convert this `Dockerfile` into a _Docker image_, is a self-contained template containing all the dependencies and configuration required to run the application. + +The `-t` flag lets us specify a name for the image, and `--pull` tells Docker to automatically download the latest version of the base image (`oven/bun`). The initial build will take longer, as Docker will download all the base images and dependencies. + +```bash +$ docker build --pull -t bun-hello-world . +[+] Building 0.9s (21/21) FINISHED + => [internal] load build definition from Dockerfile 0.0s + => => transferring dockerfile: 37B 0.0s + => [internal] load .dockerignore 0.0s + => => transferring context: 35B 0.0s + => [internal] load metadata for docker.io/oven/bun:1 0.8s + => [auth] oven/bun:pull token for registry-1.docker.io 0.0s + => [base 1/2] FROM docker.io/oven/bun:1@sha256:373265748d3cd3624cb3f3ee6004f45b1fc3edbd07a622aeeec17566d2756997 0.0s + => [internal] load build context 0.0s + => => transferring context: 155B 0.0s + # ...lots of commands... + => exporting to image 0.0s + => => exporting layers 0.0s + => => writing image sha256:360663f7fdcd6f11e8e94761d5592e2e4dfc8d167f034f15cd5a863d5dc093c4 0.0s + => => naming to docker.io/library/bun-hello-world 0.0s +``` + +--- + +We've built a new _Docker image_. Now let's use that image to spin up an actual, running _container_. + +We'll use `docker run` to start a new container using the `bun-hello-world` image. It will be run in _detached_ mode (`-d`) and we'll map the container's port 3000 to our local machine's port 3000 (`-p 3000:3000`). + +The `run` command prints a string representing the _container ID_. + +```sh +$ docker run -d -p 3000:3000 bun-hello-world +7f03e212a15ede8644379bce11a13589f563d3909a9640446c5bbefce993678d +``` + +--- + +The container is now running in the background. Visit [localhost:3000](http://localhost:3000). You should see a `Hello, World!` message. + +--- + +To stop the container, we'll use `docker stop <container-id>`. + +```sh +$ docker stop 7f03e212a15ede8644379bce11a13589f563d3909a9640446c5bbefce993678d +``` + +--- + +If you can't find the container ID, you can use `docker ps` to list all running containers. + +```sh +$ docker ps +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +7f03e212a15e bun-hello-world "bun run index.ts" 2 minutes ago Up 2 minutes 0.0.0.0:3000->3000/tcp flamboyant_cerf +``` + +--- + +That's it! Refer to the [Docker documentation](https://docs.docker.com/) for more advanced usage. |