diff options
Diffstat (limited to 'docs/guides')
-rw-r--r-- | docs/guides/ecosystem/docker.md | 140 | ||||
-rw-r--r-- | docs/guides/ecosystem/pm2.md | 54 | ||||
-rw-r--r-- | docs/guides/ecosystem/systemd.md | 113 | ||||
-rw-r--r-- | docs/guides/ecosystem/vite.md | 3 | ||||
-rw-r--r-- | docs/guides/install/trusted.md | 2 | ||||
-rw-r--r-- | docs/guides/process/ipc.md | 66 |
6 files changed, 375 insertions, 3 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. diff --git a/docs/guides/ecosystem/pm2.md b/docs/guides/ecosystem/pm2.md new file mode 100644 index 000000000..c775c8ca3 --- /dev/null +++ b/docs/guides/ecosystem/pm2.md @@ -0,0 +1,54 @@ +--- +name: Run Bun as a daemon with PM2 +--- + +[PM2](https://pm2.keymetrics.io/) is a popular process manager that manages and runs your applications as daemons (background processes). + +It offers features like process monitoring, automatic restarts, and easy scaling. Using a process manager is common when deploying a Bun application on a cloud-hosted virtual private server (VPS), as it: + +- Keeps your Node.js application running continuously. +- Ensure high availability and reliability of your application. +- Monitor and manage multiple processes with ease. +- Simplify the deployment process. + +--- + +You can use PM2 with Bun in two ways: as a CLI option or in a configuration file. + +### With `--interpreter` + +--- + +To start your application with PM2 and Bun as the interpreter, open your terminal and run the following command: + +```bash +pm2 start --interpreter ~/.bun/bin/bun index.ts +``` + +--- + +### With a configuration file + +--- + +Alternatively, you can create a PM2 configuration file. Create a file named `pm2.config.js` in your project directory and add the following content. + +```javascript +module.exports = { + name: "app", // Name of your application + script: "index.ts", // Entry point of your application + interpreter: "~/.bun/bin/bun", // Path to the Bun interpreter +}; +``` + +--- + +After saving the file, you can start your application with PM2 + +```bash +pm2 start pm2.config.js +``` + +--- + +That’s it! Your JavaScript/TypeScript web server is now running as a daemon with PM2 using Bun as the interpreter. diff --git a/docs/guides/ecosystem/systemd.md b/docs/guides/ecosystem/systemd.md new file mode 100644 index 000000000..c22fc9ae2 --- /dev/null +++ b/docs/guides/ecosystem/systemd.md @@ -0,0 +1,113 @@ +--- +name: Run Bun as a daemon with systemd +--- + +[systemd](https://systemd.io) is an init system and service manager for Linux operating systems that manages the startup and control of system processes and services. + +<!-- systemd provides aggressive parallelization capabilities, uses socket and D-Bus activation for starting services, offers on-demand starting of daemons, keeps track of processes using Linux control groups, maintains mount and auto mount points, and implements an elaborate transactional dependency-based service control logic. systemd supports SysV and LSB init scripts and works as a replacement for sysvinit. --> + +<!-- Other parts include a logging daemon, utilities to control basic system configuration like the hostname, date, locale, maintain a list of logged-in users and running containers and virtual machines, system accounts, runtime directories and settings, and daemons to manage simple network configuration, network time synchronization, log forwarding, and name resolution. --> + +--- + +To run a Bun application as a daemon using **systemd** you'll need to create a _service file_ in `/lib/systemd/system/`. + +```sh +$ cd /lib/systemd/system +$ touch my-app.service +``` + +--- + +Here is a typical service file that runs an application on system start. You can use this as a template for your own service. Replace `YOUR_USER` with the name of the user you want to run the application as. To run as `root`, replace `YOUR_USER` with `root`, though this is generally not recommended for security reasons. + +Refer to the [systemd documentation](https://www.freedesktop.org/software/systemd/man/systemd.service.html) for more information on each setting. + +```ini#my-app.service +[Unit] +# describe the app +Description=My App +# start the app after the network is available +After=network.target + +[Service] +# usually you'll use 'simple' +# one of https://www.freedesktop.org/software/systemd/man/systemd.service.html#Type= +Type=simple +# which user to use when starting the app +User=YOUR_USER +# path to your application's root directory +WorkingDirectory=/home/YOUR_USER/path/to/my-app +# the command to start the app +# requires absolute paths +ExecStart=/home/YOUR_USER/.bun/bin/bun run index.ts +# restart policy +# one of {no|on-success|on-failure|on-abnormal|on-watchdog|on-abort|always} +Restart=always + +[Install] +# start the app automatically +WantedBy=multi-user.target +``` + +--- + +If your application starts a webserver, note that non-`root` users are not able to listen on ports 80 or 443 by default. To permanently allow Bun to listen on these ports when executed by a non-`root` user, use the following command. This step isn't necessary when running as `root`. + +```bash +$ sudo setcap CAP_NET_BIND_SERVICE=+eip ~/.bun/bin/bun +``` + +--- + +With the service file configured, you can now _enable_ the service. Once enabled, it will start automatically on reboot. This requires `sudo` permissions. + +```bash +$ sudo systemctl enable my-app +``` + +--- + +To start the service without rebooting, you can manually _start_ it. + +```bash +$ sudo systemctl start my-app +``` + +--- + +Check the status of your application with `systemctl status`. If you've started your app successfully, you should see something like this: + +```bash +$ sudo systemctl status my-app +● my-app.service - My App + Loaded: loaded (/lib/systemd/system/my-app.service; enabled; preset: enabled) + Active: active (running) since Thu 2023-10-12 11:34:08 UTC; 1h 8min ago + Main PID: 309641 (bun) + Tasks: 3 (limit: 503) + Memory: 40.9M + CPU: 1.093s + CGroup: /system.slice/my-app.service + └─309641 /home/YOUR_USER/.bun/bin/bun run /home/YOUR_USER/application/index.ts +``` + +--- + +To update the service, edit the contents of the service file, then reload the daemon. + +```bash +$ sudo systemctl daemon-reload +``` + +--- + +For a complete guide on the service unit configuration, you can check [this page](https://www.freedesktop.org/software/systemd/man/systemd.service.html). Or refer to this cheatsheet of common commands: + +```bash +$ sudo systemctl daemon-reload # tell systemd that some files got changed +$ sudo systemctl enable my-app # enable the app (to allow auto-start) +$ sudo systemctl disable my-app # disable the app (turns off auto-start) +$ sudo systemctl start my-app # start the app if is stopped +$ sudo systemctl stop my-app # stop the app +$ sudo systemctl restart my-app # restart the app +``` diff --git a/docs/guides/ecosystem/vite.md b/docs/guides/ecosystem/vite.md index 03ff85472..cf77e7249 100644 --- a/docs/guides/ecosystem/vite.md +++ b/docs/guides/ecosystem/vite.md @@ -30,8 +30,7 @@ bun install Start the development server with the `vite` CLI using `bunx`. -The `--bun` flag tells Bun to run Vite's CLI using `bun` instead of `node`; by default Bun respects Vite's `#!/usr/bin/env node` [shebang line](<https://en.wikipedia.org/wiki/Shebang_(Unix)>). After Bun 1.0 this flag will no longer be necessary. - +The `--bun` flag tells Bun to run Vite's CLI using `bun` instead of `node`; by default Bun respects Vite's `#!/usr/bin/env node` [shebang line](<https://en.wikipedia.org/wiki/Shebang_(Unix)>). ```bash bunx --bun vite ``` diff --git a/docs/guides/install/trusted.md b/docs/guides/install/trusted.md index d0d841eea..0c1ac6362 100644 --- a/docs/guides/install/trusted.md +++ b/docs/guides/install/trusted.md @@ -47,4 +47,4 @@ Note that this only allows lifecycle scripts for the specific package listed in --- -See [Docs > Package manager > Trusted dependencies](/docs/cli/install#trusted-dependencies) for complete documentation of trusted dependencies. +See [Docs > Package manager > Trusted dependencies](/docs/install/lifecycle) for complete documentation of trusted dependencies. diff --git a/docs/guides/process/ipc.md b/docs/guides/process/ipc.md new file mode 100644 index 000000000..af029a524 --- /dev/null +++ b/docs/guides/process/ipc.md @@ -0,0 +1,66 @@ +--- +name: Spawn a child process and communicate using IPC +--- + +Use [`Bun.spawn()`](/docs/api/spawn) to spawn a child process. When spawning a second `bun` process, you can open a direct inter-process communication (IPC) channel between the two processes. + +{%callout%} +**Note** — This API is only compatible with other `bun` processes. Use `process.execPath` to get a path to the currently running `bun` executable. +{%/callout%} + +```ts#parent.ts +const child = Bun.spawn(["bun", "child.ts"], { + ipc(message) { + /** + * The message received from the sub process + **/ + }, +}); +``` + +--- + +The parent process can send messages to the subprocess using the `.send()` method on the returned `Subprocess` instance. A reference to the sending subprocess is also available as the second argument in the `ipc` handler. + +```ts#parent.ts +const childProc = Bun.spawn(["bun", "child.ts"], { + ipc(message, childProc) { + /** + * The message received from the sub process + **/ + childProc.send("Respond to child") + }, +}); + +childProc.send("I am your father"); // The parent can send messages to the child as well +``` + +--- + +Meanwhile the child process can send messages to its parent using with `process.send()` and receive messages with `process.on("message")`. This is the same API used for `child_process.fork()` in Node.js. + +```ts#child.ts +process.send("Hello from child as string"); +process.send({ message: "Hello from child as object" }); + +process.on("message", (message) => { + // print message from parent + console.log(message); +}); +``` + +--- + +All messages are serialized using the JSC `serialize` API, which allows for the same set of [transferrable types](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Transferable_objects) supported by `postMessage` and `structuredClone`, including strings, typed arrays, streams, and objects. + +```ts#child.ts +// send a string +process.send("Hello from child as string"); + +// send an object +process.send({ message: "Hello from child as object" }); +``` + +--- + +See [Docs > API > Child processes](/docs/api/spawn) for complete documentation. |