Home Explore Blog CI



docker

4th chunk of `content/guides/nodejs/develop.md`
5a0b69a02b16575f395e9a0b99cba06639ccaaa25fec0acc0000000100000c19
12. Add some items to the todo list to test data persistence.
13. After adding some items to the todo list, press `ctrl+c` in the terminal to
    stop your application.
14. In the terminal, run `docker compose rm` to remove your containers.

    ```console
    $ docker compose rm
    ```

15. Run `docker compose up` to run your application again.

    ```console
    $ docker compose up --build
    ```

16. Refresh [http://localhost:3000](http://localhost:3000) in your browser and verify that the todo items persisted, even after the containers were removed and ran again.

## Configure and run a development container

You can use a bind mount to mount your source code into the container. The container can then see the changes you make to the code immediately, as soon as you save a file. This means that you can run processes, like nodemon, in the container that watch for filesystem changes and respond to them. To learn more about bind mounts, see [Storage overview](/manuals/engine/storage/_index.md).

In addition to adding a bind mount, you can configure your Dockerfile and `compose.yaml` file to install development dependencies and run development tools.

### Update your Dockerfile for development

Open the Dockerfile in an IDE or text editor. Note that the Dockerfile doesn't
install development dependencies and doesn't run nodemon. You'll
need to update your Dockerfile to install the development dependencies and run
nodemon.

Rather than creating one Dockerfile for production, and another Dockerfile for
development, you can use one multi-stage Dockerfile for both.

Update your Dockerfile to the following multi-stage Dockerfile.

```dockerfile {hl_lines="5-26",collapse=true,title=Dockerfile}
# syntax=docker/dockerfile:1

ARG NODE_VERSION=18.0.0

FROM node:${NODE_VERSION}-alpine as base
WORKDIR /usr/src/app
EXPOSE 3000

FROM base as dev
RUN --mount=type=bind,source=package.json,target=package.json \
    --mount=type=bind,source=package-lock.json,target=package-lock.json \
    --mount=type=cache,target=/root/.npm \
    npm ci --include=dev
USER node
COPY . .
CMD npm run dev

FROM base as prod
RUN --mount=type=bind,source=package.json,target=package.json \
    --mount=type=bind,source=package-lock.json,target=package-lock.json \
    --mount=type=cache,target=/root/.npm \
    npm ci --omit=dev
USER node
COPY . .
CMD node src/index.js
```

In the Dockerfile, you first add a label `as base` to the `FROM
node:${NODE_VERSION}-alpine` statement. This lets you refer to this build stage
in other build stages. Next, you add a new build stage labeled `dev` to install
your development dependencies and start the container using `npm run dev`.
Finally, you add a stage labeled `prod` that omits the dev dependencies and runs
your application using `node src/index.js`. To learn more about multi-stage
builds, see [Multi-stage builds](/manuals/build/building/multi-stage.md).

Next, you'll need to update your Compose file to use the new stage.

### Update your Compose file for development

To run the `dev` stage with Compose, you need to update your `compose.yaml`

Title: Testing Persistence and Configuring Development Container
Summary
This section guides you through testing data persistence, stopping the application, removing containers, and running it again. It then discusses configuring a development container using bind mounts. The focus shifts to updating the Dockerfile for development by creating a multi-stage Dockerfile, including stages for development and production. The final step involves preparing to update the Compose file to use the new development stage.