Under the original deployment script, each deployment of my node application takes more than 10 minutes, and my project is not suitable for multi-stage construction, so I tried various ways to let it use the image layer to cache part of the installation process, but there was something wrong with it.
It seems that if you want to avoid problems, you should run the installation process completely at the time of deployment. In this way, you can only use the npm cache to shorten the deployment time.
Step 1: Hang an external cache
I thought it was impossible to bind a volume like a container to make the process file persistent during the construction of the dockerfile. But yesterday I found that there is a docker that needs to be updated, which is part of the Buildkit feature. This feature is only available in dockers after 18.09. In short, it can be used after upgrading the docker to the latest version.
The method is simple, as shown in Dockerfile:
FROM node:18.18.1-buster-slim RUN apt update &&\ apt install -y git openssh-client python3 curl COPY ./ deploy /deploy COPY ./ app/ /app RUN -- mount=type=cache, target=/root/. npm Sh/deploy/install.sh # Then execute your installation script WORKDIR "/deploy" ENTRYPOINT ["/bin/sh"] CMD [ "./start.sh" ] EXPOSE 80
In this way, the '/root/. npm' of the construction container will be mapped to the general docker cache during the construction of the docker file. I tested that if the same cache is attached to other images, the cache can also be used during the construction of other images, but the FROM images of other images are the same, I don't know whether the cache mount will be affected if the source image changes.
be careful: ~/. npm is the default cache directory of npm under Linux, but the default cache directory can be changed. If you modify the default cache directory address of npm in your project, you should also change it here. Or if your platform is special and the default directory of npm is not here, you should also modify it accordingly.
In addition to attaching the cache (type=cache), you can also bind external files or directories (type=bind). The relevant information is here https://docs.docker.com/build/guide/mounts/ However, this document is a bit confusing. I didn't write the source and target which are inside and which are outside. I wrote the external path in the source and it told me that the file does not exist. Then I used the cache directly and didn't try again.
If you think there is a problem with the files cached during the construction process, or simply want to clear these caches, you can According to the method here , execute the following command:
docker builder prune --filter type=exec.cachemount
If there is no effect, you can try to remove the – filter and its parameters.
Step 2: Let npm use cache first (optional)
When installing dependencies, npm will send a request to the server to check whether each local cache has expired, even if there is a local cache. This process is also very long. In fact, even if the cache expires, it is not a problem. Normally, the contents of packages with the same version number will not change. Therefore, you can let NPM give priority to the local cache and skip checking its online status, which can greatly reduce the installation time.
The method is very simple. Just add a '- preference offline' parameter to the installation command:
npm i --prefer-offline #You can also add a -- verbose parameter to confirm whether the cache is really used npm i --prefer-offline --verbose
After this, the subsequent deployment time of the application is shortened from the original ten minutes to ten minutes without any change More than one minute , which can be called rocket acceleration, finally solved a problem that has puzzled me for more than a year.