Nest in docker

In the Nest. Js project, the Dockers image is essential in order to deploy to the server. Nest itself doesn’t come with a dockerfile, so this part needs to be created manually. Now let’s try writing a DockerFile for a Nest project.

Project preparation

Create a new Nest project using the Nest CLI

npm i -g @nestjs/cli
nest new project-name
Copy the code

The project structure is as follows:

compile

It is possible to run TS code directly when debugging Nest natively, but node.js is not actually a TS runtime, so Nest actually relies on TS-Node to compile the code in memory into JS code and run it. On the server, the code doesn’t change and doesn’t need to be debugged, so there’s no need to continue using TS code, but compile it to JS code.

yarn build
Copy the code

Get the dist folder:

Write the simplest dockerfile

Create a new dockerFile

FROM node:lts-alpine
ENV NODE_ENV=production
WORKDIR /app
COPY ./dist .
EXPOSE 3000
CMD ["node"."main.js"]
Copy the code

Add node_modules to docker

The minimalist image is not available because the project cannot be started without node_modules support. It is also not possible to copy the local node_modules into docker, and node_modules from different operating systems and environments cannot be mixed. Instead, add the package.json file to Docker, download the dependency, and then remove it (or not, but then the file will be useless).

FROM node:lts-alpine
ENV NODE_ENV=production
WORKDIR /app
COPY ["package.json"."yarn.lock".". /"]
RUN yarn --production --silent
RUN rm package.json yarn.lock
COPY ./dist .
EXPOSE 3000
CMD ["node"."main.js"]
Copy the code

Limit the copy of a file

Although you can get Hello World by visiting http://localhost:3000/! , but observing the Docker image, the file structure is as follows:

It’s easy to see that there’s a big problem here: there are many more non-.js files, increasing docker’s space. And in fact. Ts. D. Js. The map is debug file, and tsconfig. Build. Tsbuildinfo is compiled information, is don’t need these files to the runtime. Modifying the tscofig. Josn file may not generate these files, but it will affect debugging, so it is not recommended. The simplest thing to do is to copy only the JS and JSON files (some configuration will be in the JSON file) when copying the files.

FROM node:lts-alpine
ENV NODE_ENV=production
WORKDIR /app
COPY ["package.json"."yarn.lock".". /"]
RUN yarn --production --silent
RUN rm package.json yarn.lock
COPY ["./dist/*.js"."./dist/*.json".". /"]
EXPOSE 3000
CMD ["node"."main.js"]
Copy the code

Then you look at the folder and you only get a clean run file

Copies of subdirectories

As the project develops, the directory structure will no longer be a single file and the hierarchy will become more complex. We hope that the JS files in the final image will need to maintain the same directory hierarchy and structure as the original TS.

Suppose our project introduces the CATS module and therefore creates a subfile cats. Here’s the original folder:

The compiled dist folder is as follows

But there is no cats folder in a Docker image

The COPY command copies only the files in the folder, does not COPY the folder, and does not preserve the directory hierarchy. To keep the file hierarchy to only use.dist/ when copying, but this can lead to multiple copies of files, an alternative to choosing which files to copy is to use.dockerignore and in turn exclude unwanted files. Dockerfile is as follows:

FROM node:lts-alpine
ENV NODE_ENV=production
WORKDIR /app
COPY ["package.json"."yarn.lock".". /"]
RUN yarn --production --silent
RUN rm package.json yarn.lock
COPY ./dist/ .
EXPOSE 3000
CMD ["node"."main.js"]
Copy the code

Then add it in the.dockerIgnore file

**/*.js.map
**/*.d.ts
**/tsconfig.build.tsbuildinfo
Copy the code

Then you can build a Docker image that maintains the file hierarchy and only has JS and JSON files.

To use

Dockerfile needs to be used on CI after writing, but it is not easy to use directly. After downloading the code, before running Docker build, you still need to run Yarn Lint YARN build Yarn Test. There is also a dependency cache. If you don’t do this, you need to download the dependency from the NPM source for each inheritance. When this is all done, a simple CI is built.