赞
踩
流程如下:
docker file:
# specify a base image
FROM alpine
# install dependencies
RUN npm install
# default command
CMD [ "npm", "start" ]
⚠️ 这里使用的基础镜像是 alpine。
package.json:
{
"dependencies": {
"express": "*",
"redis": "2.8.0"
},
"scripts": {
"start": "node index.js"
}
}
index.js:
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('Hi there')
});
app.listen(9999, () => {
console.log('Listening on port 9999');
});
运行Docker,其运行结果如下:
➜ visits-starter docker build .
Sending build context to Docker daemon 19.46kB
Step 1/3 : FROM alpine
latest: Pulling from library/alpine
213ec9aee27d: Already exists
Digest: sha256:bc41182d7ef5ffc53a40b044e725193bc10142a1243f395ee852a8d9730fc2ad
Status: Downloaded newer image for alpine:latest
---> 9c6f07244728
Step 2/3 : RUN npm install
---> Running in facd3767fa67
/bin/sh: npm: not found
The command '/bin/sh -c npm install' returned a non-zero code: 127
报错的原因是因为 alpine 中并没有 node 相关的包,因此直接运行 npm install
会抛出 npm: not found
的错。这个时候比较简单的解决方案:
下载、配置并安装 node
使用别人已经打包好的基础镜像,这里使用的是 node:14-alpine
。我尝试使用 v16,不过似乎是有一些配置问题,直接运行会导致报错。
目前 v14 的支持一直到 2023-04-30……不知道之后是不是会考虑直接升级到 v18 还是 v20.
修正后的部分:
# specify a base image
# FROM alpine - remove
# and replace with
FROM node:14-alpine
运行结果:
➜ visits-starter docker build . Sending build context to Docker daemon 19.46kB Step 1/3 : FROM node:14-alpine ---> 798752c1e2a0 Step 2/3 : RUN npm install ---> Running in f980f1bc6709 npm WARN saveError ENOENT: no such file or directory, open '/package.json' npm notice created a lockfile as package-lock.json. You should commit this file. npm WARN enoent ENOENT: no such file or directory, open '/package.json' npm WARN !invalid#2 No description npm WARN !invalid#2 No repository field. npm WARN !invalid#2 No README data npm WARN !invalid#2 No license field. up to date in 0.436s found 0 vulnerabilities Removing intermediate container f980f1bc6709 ---> 9575921d8a0b Step 3/3 : CMD [ "npm", "start" ] ---> Running in 2eac9cfdffcd Removing intermediate container 2eac9cfdffcd ---> a6c1af8bcdbd Successfully built a6c1af8bcdbd Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
虽然在运行Docker的时候没有报错,不过我尝试运行了一下 npm start
还是报错了,运行结果如下:
➜ visits-starter docker run -it a6c1af8bcdbd sh / # ls bin etc lib mnt package-lock.json root sbin sys usr dev home media opt proc run srv tmp var / # npm start npm ERR! code ENOENT npm ERR! syscall open npm ERR! path /package.json npm ERR! errno -2 npm ERR! enoent ENOENT: no such file or directory, open '/package.json' npm ERR! enoent This is related to npm not being able to find a file. npm ERR! enoent npm ERR! A complete log of this run can be found in: npm ERR! /root/.npm/_logs/2022-10-06T18_04_50_719Z-debug.log / #
应用并没有运行,并且爆出错误 package.json 找不到的错。
会出现这个错误的原因是因为每一个运行的镜像是当前系统的一个snapshot,而本地的文件——package.json, index.js——并没有复制到镜像中,因此在运行的时候,node会找不到package.json去运行。
这个时候就需要使用一个新的指令:COPY
去将本地文件复制到镜像中去:
# specify a base image
FROM node:14-alpine
# copy from locak system to docker temp container
COPY ./ ./
# install dependencies
RUN npm install
# default command
CMD [ "npm", "start" ]
运行结果:
➜ visits-starter docker build . Sending build context to Docker daemon 19.46kB Step 1/4 : FROM node:14-alpine ---> 798752c1e2a0 Step 2/4 : COPY ./ ./ ---> 22d75ba79400 Step 3/4 : RUN npm install ---> Running in 5065b9da7657 npm notice created a lockfile as package-lock.json. You should commit this file. npm WARN !invalid#2 No description npm WARN !invalid#2 No repository field. npm WARN !invalid#2 No license field. added 61 packages from 46 contributors and audited 61 packages in 3.026s 7 packages are looking for funding run `npm fund` for details found 1 high severity vulnerability run `npm audit fix` to fix them, or `npm audit` for details Removing intermediate container 5065b9da7657 ---> 05230fcb61cc Step 4/4 : CMD [ "npm", "start" ] ---> Running in 372aba7de32a Removing intermediate container 372aba7de32a ---> 147ae3af863d Successfully built 147ae3af863d Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
注意这里:added 61 packages from 46 contributors and audited 61 packages in 3.026s
,这是可以确认package.json中的所有文件被下载了。
随后运行这个docker镜像:
➜ visits-starter docker run 147ae3af863d
> @ start /
> node index.js
Listening on port 9999
目前程序已经可以运行,也在监听9999这个端口,但是当打开浏览器时,浏览器没法打开该网址。
这是因为镜像的路由并没有设置,本地无法访问镜像内部的端口。当然,docker默认禁止对内访问,对外访问是可以进行的——不然node的包也没办法下载成功。
路由配置(port mapping) 只能在运行时进行操作,因此可以运行下面的指令:
我用了tag这样输入指令起来方便点
# outsite port does not have to be same as image port
➜ visits-starter docker run -p 9999:9999 ga/v
> @ start /
> node index.js
Listening on port 9999
运行成功后:
继续访问镜像并且看一下目前的目录结构:
➜ visits-starter docker run -it ga/v sh
/ # ls
Dockerfile etc lib node_modules package.json root srv usr
bin home media opt pnpm-lock.yaml run sys var
dev index.js mnt package-lock.json proc sbin tmp
/ #
这个文件比较小还不要紧,但是文件比较大的时候就可能会出现重写系统默认文件的情况。Docker也提供了可以设置working directory的指令,这样可以让所有的文件复制到该working directory下。
Dockerfile更新如下:
# specify a base image
FROM node:14-alpine
# specify a working dir
WORKDIR /usr/app
# copy from locak system to docker temp container
COPY ./ ./
# install dependencies
RUN npm install
# default command
CMD [ "npm", "start" ]
之后运行指令查看目录结构:
➜ visits-starter docker run -it ga/v sh
/usr/app # ls
Dockerfile index.js node_modules package-lock.json package.json pnpm-lock.yaml
/usr/app # pwd
/usr/app
/usr/app #
这一步是为了可以让修改源代码不影响node包的安装。Docker对比指令,一旦发现指令与先前的不同——如修改了源码,那么整个COPY ...
,RUN ...
, CMD ...
的步骤全都会重新运行,这也就代表着所有的依赖包都会被重新下载。
为了提升性能,可以将复制 package.json
与其他代码的操作分开,这样只要 package.json
不被修改,那么代码就不会重新下载 node 依赖包。
# specify a base image
FROM node:14-alpine
# specify a working dir
WORKDIR /usr/app
# copy from locak system to docker temp container
COPY ./package.json ./
# install dependencies
RUN npm install
COPY ./ ./
# default command
CMD [ "npm", "start" ]
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。