NOTE
本指南假设你已经安装了 [Docker Desktop](https://www.docker.com/products/docker-desktop/)。Docker 是一个用于将应用打包并作为轻量级、可移植的 容器 运行的平台,该容器封装了所有必要的依赖项。
要 容器化 我们的应用,我们需要定义一个 Dockerfile。此文件包含一系列指令,用于初始化容器、将本地项目文件复制到其中、安装依赖项并启动应用。
# 使用官方 Bun 镜像
# 在 https://hub.docker.com/r/oven/bun/tags 查看所有版本
FROM oven/bun:1 AS base
WORKDIR /usr/src/app
# 将依赖安装到临时目录
# 这将缓存它们并加速未来的构建
FROM base AS install
RUN mkdir -p /temp/dev
COPY package.json bun.lock /temp/dev/
RUN cd /temp/dev && bun install --frozen-lockfile
# 使用 --production 安装(排除 devDependencies)
RUN mkdir -p /temp/prod
COPY package.json bun.lock /temp/prod/
RUN cd /temp/prod && bun install --frozen-lockfile --production
# 从临时目录复制 node_modules
# 然后复制所有(未被忽略的)项目文件到镜像中
FROM base AS prerelease
COPY --from=install /temp/dev/node_modules node_modules
COPY . .
# [可选] 测试和构建
ENV NODE_ENV=production
RUN bun test
RUN bun run build
# 将生产依赖和源代码复制到最终镜像
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 .
# 运行应用
USER bun
EXPOSE 3000/tcp
ENTRYPOINT [ "bun", "run", "index.ts" ]现在你已经有了 Docker 镜像,让我们看看 .dockerignore,它的语法与 .gitignore 相同,在这里你需要指定在 Docker 构建的任何阶段都不能包含的文件/目录。下面是一个忽略文件的示例
node_modules
Dockerfile*
docker-compose*
.dockerignore
.git
.gitignore
README.md
LICENSE
.vscode
Makefile
helm-charts
.env
.editorconfig
.idea
coverage*现在我们将使用 docker build 将这个 Dockerfile 转换为 Docker 镜像,这是一个独立的模板,包含运行应用所需的所有依赖项和配置。
-t 标志允许我们为镜像指定一个名称,--pull 告诉 Docker 自动下载基础镜像(oven/bun)的最新版本。初始构建会花费更长时间,因为 Docker 需要下载所有基础镜像和依赖项。
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我们已经构建了一个新的 Docker 镜像。现在让我们使用该镜像启动一个实际运行的 容器。
我们将使用 docker run 使用 bun-hello-world 镜像启动一个新容器。它将以 分离 模式(-d)运行,我们将把容器的 3000 端口映射到本地机器的 3000 端口(-p 3000:3000)。
run 命令会打印一个代表 容器 ID 的字符串。
docker run -d -p 3000:3000 bun-hello-world7f03e212a15ede8644379bce11a13589f563d3909a9640446c5bbefce993678d容器现在在后台运行。访问 localhost:3000。你应该会看到一条 Hello, World! 消息。
要停止容器,我们使用 docker stop <container-id>。
docker stop 7f03e212a15ede8644379bce11a13589f563d3909a9640446c5bbefce993678d如果你找不到容器 ID,可以使用 docker ps 列出所有正在运行的容器。
docker psCONTAINER 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就是这样!请参阅 Docker 文档 了解更多高级用法。