本文从 0 开始部署一个 Node.js (Remix) 为例,本文本将镜像放在 ali 云上,备份。
一、技术栈准备
- 本地 docker
- 一台服务器(以阿里云云服务为例)
- Docker 镜像存储库(阿里镜像服务)
- Node.js 项目(Remix + Prisma + PostreSQL)
- Dockerfile
- Nginx
- cerbot
二、为什么?
- 在服务器和本地机器之间需要一个 DockerHub, 但是不想想将内容托管了 DockerHub 上开源。
- 在阿里云上将镜像设为私有比较符合需求。
- 服务器配置问题。如果我们服务器比较小,但是我们项目比较大,在本地构建的时候没有问题,但是到了服务器上就可能因为机器限制不能构建成功。
三、安装 Docker
首先需要本地和服务器 都安装 docker, 根据不同的系统安装即可。
服务推荐安装社区版本的。
四、注册阿里云并开通个人镜像服务
本文基于阿里云镜像服务,没有阿里云可以考虑开通一个,注册并开通个人镜像服务。
如果找不到,可以
容器镜像服务ACR
如果已经开通了个人版,显示应该是同上面的。但是会有实现使用限制:
- 仓库:限额
300 - 命名空间:
3个
这些空间其实,个人项目也够用了。也可以在 获取凭证 中修改自己的固定密码,这样就可以在终端使用自己固定的 aliyun Registry 进行登录了.
五、终端登录阿里云账号
sudo docker login --username=<your_aliyun_name> registry.<your_region>.aliyuncs.com
本地和服务器都需要使用阿里云账号登录。
六、开始一个 Remix 项目
这里以 Remix 为例,其他的编程语言,或者 Next.js 其实都差不多。
npx create-remix ali-docker-remix-demo
七、编写 Dockrefile
FROM node:20.11.1-alpine3.19 AS dependencies
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
ARG DATABASE_URL
ENV DATABASE_URL=${DATABASE_URL}
RUN npm config set registry https://registry.npmmirror.com \
&& npm install -g pnpm \
&& pnpm install --prod=false
FROM dependencies AS build
COPY . .
RUN npx prisma generate
RUN NODE_OPTIONS=--max-old-space-size=4096 pnpm run build
# RUN pnpm prune --prod
FROM node:20.11.1-alpine3.19 AS runtime
WORKDIR /app
RUN npm config set registry https://registry.npmmirror.com \
&& npm install -g pnpm
COPY --from=build /app/node_modules ./node_modules
COPY --from=build /app/build ./build
COPY --from=build /app/prisma ./prisma
COPY --from=build /app/package.json ./
COPY --from=build /app/pnpm-lock.yaml ./
ARG DATABASE_URL
ENV DATABASE_URL=${DATABASE_URL}
EXPOSE 3000
CMD ["pnpm", "run", "start"]
这是一个优化过后端的 Dockerfile, 这里使用了 Prisma 链接数据库,使用分阶段构建进行,移除了非生产所需的内容,优化构建体积。
如果有更加复杂应用,如使用了数据库,redis, nginx, oss可以考虑使用 docker-compose 组合这里简单就直接使用 Dockerfile 了。
八、构建 docker 镜像
本机构建docker 进行镜像:
docker build --build-arg DATABASE_URL=postgresql://<user_name>:<password>@<host>:<port>/<db_name>?schema=public -t registry.<origin>.aliyuncs.com/<name_space>/<image_name>:<image_version> .
# 找到目标镜像 id
docker images
# 打上 tag
docker tag [ImageId] registry.<origin>.aliyuncs.com/<name_space>/<image_name>:[镜像版本号]
使用 docker build 指定参数数据地址参数构建。
九、上传 aliyuan 镜像
# 登录
docker login --username=<user_name> registry.<origin_name>.aliyuncs.com
# 按照镜像 tag 上传
docker push registry.<origin>.aliyuncs.com/<name_space>/<image_name>:[镜像版本号]
登录并将服务器上传到阿里云。上传之后可以在云服务后台查看自己的上传的进行是否成功。
十、在服务器拉取镜像
进入自己的服务器,这里以阿里云云服务为例:
# 登录
docker login --username=<user_name> registry.<origin_name>.aliyuncs.com
# 拉取镜像
docker pull registry.<origin>.aliyuncs.com/<name_space>/<image_name>:[镜像版本号]
十一、运行镜像为容器
如果你的老项目还在运行,先停止
docker ps # 找到你的老项目<容器 id>
docker stop <container_id>
# 指定端口运行容器
docker run -p <your_port>:<container_port> -itd <container_id>
# 如果有需要可以删除老容器和镜像
docker ps -a # 找到所有容器和<容器 id>
docker rm <container_id>
docker images # 找到所有的镜像和镜像 id
docker rmi <image_id>
十二、查看镜像 logs
当然可以容器运行了情况如何也可能也需要查看一下:
docker ps # 查看正在运行的容器列表
docker ps -a # 如果运行出错,镜像不会运行
docker logs <container_id> # 输出运行后的输出
如果项目正常输出,就正常运行了
十三、ngnix
如果使用了单独 nginx 进行反向代理,可能还需要配置,并重启一下 nignx 配置。
server {
server_name <your_server_name>;
gzip on;
gzip_min_length 1k;
gzip_buffers 4 32;
gzip_comp_level 6;
gzip_types text/plain application/c-javascript application/javascript text/javascript;
gzip_vary on;
gzip_disable "MSIE [1-6]\.";
location / {
proxy_pass http://localhost:<port>;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
}
access_log /var/log/nginx/<your_logs_dir>/access.log;
error_log /var/log/nginx/<your_logs_dir>/error.log;
}
这里给了一些基本的 nginx 配置,包含gzip 压缩、本地服务代理(也就是我们 Node.js 服务),header、host 等,以及 access、error 日志保存。如果需要 ssl 证书可以使用 certbot 的服务,配合定时任务完成续签。
sudo systemctl restart nginx # 重启
sudo systemctl status nginx # 查看 nginx 状态
十四、域名与防火墙
如果有自己的域名,绑定自己域名与服务器,并在服务器打开端口防火墙限制。然后测试服务器是否正常访问。
十五、小结
本文主要探索和实践 Docker 部署 Node.js 项目(Remix 为例),从为什么需要一个私有的 Register 到本地构建到服务端运行容器,一整流程流程。最后希望能够帮助到大家。