docker安装以及部署node项目
源码地址
同路之人,幸得君顾,盼得君之一赞!
与君同行,愿得青眼相加!
你的star
如春风化雨,润物无声;
如山间清泉,滋润心田;
如长河落日,映照初心;
亦如暗夜明灯,照亮前路;
是吾辈前行之明灯,亦是我坚持的动力!
愿君前程似锦,代码如诗,人生如画!
【GIthub地址】(github.com/lintaibai/T...)
【Gitee地址】(gitee.com/lintaibai/T...)
1、认识
下载地址
注意我们一般采取Docker Desktop进行管理,就相当于我们的版本或者镜像综合的一个管理工具
javascript
// 官方网址
https://docs.docker.com/get-started/introduction/get-docker-desktop/
// 查看版本
docker --version
Docker version 28.5.2, build ecc6942
// 国内阿里镜像地址
https://developer.aliyun.com/mirror/
docker常用命令
javascript
# 列出所有本地镜像
docker images
# 或者使用更详细的格式
docker image ls
// 删除镜像
# 通过镜像ID删除
docker rmi <image_id>
# 通过镜像名删除
docker rmi <image_name>:<tag>
# 示例
docker rmi ubuntu:20.04
# 删除多个指定镜像
docker rmi <image1> <image2> <image3>
介绍
Docker 是一个开源的容器化平台,它可以将应用程序及其依赖项打包到一个轻量级、可移植的容器中。简单来说,Docker 让你能够将你的应用和运行环境打包在一起,确保在任何地方都能以相同的方式运行。
Docker 已经成为现代软件开发和部署的重要工具,特别是在微服务架构和 DevOps 实践中。
主要特点和优势
- 轻量级:容器共享主机操作系统的内核,不需要像虚拟机那样运行完整的操作系统,因此更加轻量。
- 可移植性:容器可以在任何支持 Docker 的环境中运行,包括开发者的笔记本电脑、测试服务器、生产环境等。
- 一致性:确保应用在开发、测试和生产环境中表现一致,消除"在我电脑上能运行"的问题。
- 快速部署:容器的启动速度非常快,通常只需几秒钟。
- 资源效率高:与虚拟机相比,容器占用的资源更少,可以在同一台机器上运行更多容器。
- 版本控制:Docker 镜像可以像代码一样进行版本控制,便于追踪和管理变更。
Docker 的基本概念
- 镜像(Image):一个只读的模板,用于创建容器。
- 容器(Container):镜像的运行实例,是轻量级、可执行的独立软件包。
- 仓库(Repository):用于存储和分发镜像的地方,如 Docker Hub
相关镜像源
docker国内的常见镜像源
javascript
DaoCloud 镜像站:https://docker.m.daocloud.io
网易云:https://hub-mirror.c.163.com
百度云:https://mirror.baidubce.com
南京大学镜像站:https://docker.nju.edu.cn
设置镜像源
javascript
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://hub-mirror.c.163.com",
"https://mirror.baidubce.com",
"https://docker.nju.edu.cn"
]
}
EOF
// 重启docker服务
sudo systemctl daemon-reload
sudo systemctl restart docker
镜像源信息查看
javascript
// 查看当前生效的镜像源
# 查看Docker信息
docker info
# 在输出中查找Registry Mirrors部分
// 查看设置的镜像源
cat /etc/docker/daemon.json
// 查看镜像源
docker info | grep -i "Registry Mirrors" -A 5
完整的镜像源及地址
javascript
"registry-mirrors": [
"https://mirrors.tuna.tsinghua.edu.cn/docker-ce", // 清华大学镜像站
"https://docker.m.daocloud.io", // DaoCloud 镜像站
"https://hub-mirror.c.163.com", // 网易云
"https://mirror.baidubce.com", // 百度云
"https://docker.nju.edu.cn" // 南京大学镜像站
]
2、安装使用
Mac上安装Docker
1、下载地址
选择自己对应的版本下载即可
javascript
https://www.docker.com/products/docker-desktop/
汉化Docker Desktop
Docker Desktop 是一个让开发者能够在 Windows 和 macOS 上轻松使用 Docker 的应用程序。
javascript
下载对应Docker Desktop版本号、操作系统的汉化包
服务器安装Docker
进入我们的服务器,我的演示为ubuntu服务器
以linux系统的主机为最佳
javascript
下载安装的官网
https://get.docker.com/
第一个和第四个命令
// 添加Docker官方GPG密钥
curl -fsSL https://get.docker.com -o install-docker.sh
sudo sh install-docker.sh
// 系统建议安装命令
sudo apt install docker.io
// 验证是否安装成功
docker --version
3、使用
DockerFile文件配置
Docker打包项目一般都要新建DockerFile文件,以rust为例,内容如下
javascript
# 构建阶段
FROM rust:1.70 as builder
WORKDIR /app
# 优化编译
ENV RUSTFLAGS="-C target-feature=+crt-static"
ENV CARGO_TERM_COLOR=always
COPY Cargo.toml ./
RUN mkdir src && echo "fn main() {}" > src/main.rs && cargo build --release
RUN rm -rf src
COPY src ./src
RUN cargo build --release
# 运行阶段
FROM scratch
# 从构建阶段复制编译好的二进制文件和SSL证书(如果需要HTTPS)
COPY --from=builder /app/target/release/nexus-rust-api /nexus-rust-api
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
EXPOSE 3300
CMD ["/nexus-rust-api"]
添加权限
将用户添加到docker组
plain
sudo usermod -aG docker $USER
# 然后重新登录或执行:
newgrp docker
打包构建
javascript
# 构建镜像
docker build -t nexus-rust-api .
没有将用户添加到用户组可以用这个命令构建镜像
sudo docker build -t nexus-rust-api .
# 运行容器
docker run -p 3300:3300 nexus-rust-api
打包过程一直失败,这里我们需要使用国内镜像进行加速
javascript
国内镜像加速
# 创建或编辑daemon.json
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": [
"https://docker.mirrors.ustc.edu.cn",
"https://hub-mirror.c.163.com"
]
}
EOF
// 以下命令验证配置是否生效:出现刚刚的镜像源就是成功了
docker info | grep -A 10 "Registry Mirrors"
// 配置阿里官方镜像库
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://registry.cn-hangzhou.aliyuncs.com"]
}
EOF
# 重启Docker服务
sudo systemctl daemon-reload
sudo systemctl restart docker
Docker国内镜像地址
javascript
https://www.cnblogs.com/wzzkaifa/p/19041828
# 停止Docker服务
sudo systemctl stop docker
# 配置新的镜像源
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://docker.1ms.run"]
}
EOF
# 重启Docker服务
sudo systemctl daemon-reload
sudo systemctl start docker
# 验证配置
docker info | grep -A 10 "Registry Mirrors"
// DockerFile文件配置
# 构建阶段
FROM docker.1ms.run/library/rust:1.70 as builder
WORKDIR /app
COPY Cargo.toml ./
RUN mkdir src && echo "fn main() {}" > src/main.rs && cargo build --release
RUN rm -rf src
COPY src ./src
RUN cargo build --release
# 运行阶段
FROM scratch
COPY --from=builder /app/target/release/nexus-rust-api /nexus-rust-api
EXPOSE 3300
CMD ["/nexus-rust-api"]
docker build -t nexus-rust-api .
FROM rust:1.75
WORKDIR /app
COPY . .
RUN cargo build --release
CMD ["./target/release/nexus-rust-api"]
配置信息
本地我的配置
javascript
sudo mkdir -p /etc/docker
// 清华大学
"https://mirrors.tuna.tsinghua.edu.cn/docker-ce"
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": [
"https://mirrors.tuna.tsinghua.edu.cn/docker-ce",
"https://ccr.ccs.tencentyun.com",
"https://docker.1ms.run",
"https://hub-mirror.c.163.com",
"https://mirror.baidubce.com",
"https://do.nark.eu.org",
"https://dc.j8.work",
"https://docker.m.daocloud.io",
"https://dockerproxy.com",
"https://docker.mirrors.ustc.edu.cn",
"https://docker.nju.edu.cn",
"https://docker.1panel.live",
"https://docker.1panelproxy.com",
"https://elastic.m.daocloud.io",
"https://elastic.m.daocloud.io",
"https://docker.m.daocloud.io",
"https://gcr.m.daocloud.io",
"https://ghcr.m.daocloud.io",
"https://k8s-gcr.m.daocloud.io",
"https://k8s.m.daocloud.io",
"https://mcr.m.daocloud.io",
"https://nvcr.m.daocloud.io",
"https://quay.m.daocloud.io"
]
}
EOF
借鉴配置
javascript
https://github.com/rust-cross/rust-musl-cross.git
FROM ubuntu:22.04
ENV DEBIAN_FRONTEND=noninteractive
# Make sure we have basic dev tools for building C libraries. Our goal
# here is to support the musl-libc builds and Cargo builds needed for a
# large selection of the most popular crates.
#
RUN apt-get update && \
apt-get install -y \
build-essential \
cmake \
curl \
file \
git \
sudo \
xutils-dev \
unzip \
ca-certificates \
python3 \
python3-pip \
autoconf \
autoconf-archive \
automake \
flex \
bison \
llvm-dev \
libclang-dev \
clang \
&& \
apt-get clean && rm -rf /var/lib/apt/lists/*
# Install Let's Encrypt R3 CA certificate from https://letsencrypt.org/certificates/
COPY lets-encrypt-r3.crt /usr/local/share/ca-certificates
RUN update-ca-certificates
ARG TARGET=x86_64-unknown-linux-musl
ARG MUSL_TARGET=$TARGET
ENV RUST_MUSL_CROSS_TARGET=$MUSL_TARGET
ARG RUST_MUSL_MAKE_CONFIG=config.mak
COPY $RUST_MUSL_MAKE_CONFIG /tmp/config.mak
RUN cd /tmp && \
git clone --depth 1 https://github.com/richfelker/musl-cross-make.git && \
cp /tmp/config.mak /tmp/musl-cross-make/config.mak && \
cd /tmp/musl-cross-make && \
export CFLAGS="-fPIC -g1 $CFLAGS" && \
export TARGET=$MUSL_TARGET && \
if [ `dpkg --print-architecture` = 'armhf' ] && [ `uname -m` = 'aarch64' ]; then SETARCH=linux32; else SETARCH= ; fi && \
$SETARCH make -j$(nproc) > /tmp/musl-cross-make.log && \
$SETARCH make install >> /tmp/musl-cross-make.log && \
ln -s /usr/local/musl/bin/$TARGET-strip /usr/local/musl/bin/musl-strip && \
cd /tmp && \
rm -rf /tmp/musl-cross-make /tmp/musl-cross-make.log
RUN mkdir -p /home/rust/libs /home/rust/src
# Set up our path with all our binary directories, including those for the
# musl-gcc toolchain and for our Rust toolchain.
ENV PATH=/root/.cargo/bin:/usr/local/musl/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
ENV TARGET_CC=$MUSL_TARGET-gcc
ENV TARGET_CXX=$MUSL_TARGET-g++
ENV TARGET_AR=$MUSL_TARGET-ar
ENV TARGET_RANLIB=$MUSL_TARGET-ranlib
ENV TARGET_HOME=/usr/local/musl/$MUSL_TARGET
ENV TARGET_C_INCLUDE_PATH=$TARGET_HOME/include/
# pkg-config cross compilation support
ENV TARGET_PKG_CONFIG_ALLOW_CROSS=1
ENV TARGET_PKG_CONFIG_SYSROOT_DIR=$TARGET_HOME
ENV TARGET_PKG_CONFIG_PATH=$TARGET_HOME/lib/pkgconfig:/usr/local/musl/lib/pkgconfig
ENV TARGET_PKG_CONFIG_LIBDIR=$TARGET_PKG_CONFIG_PATH
# We'll build our libraries in subdirectories of /home/rust/libs. Please
# clean up when you're done.
WORKDIR /home/rust/libs
RUN export CC=$TARGET_CC && \
export C_INCLUDE_PATH=$TARGET_C_INCLUDE_PATH && \
export AR=$TARGET_AR && \
export RANLIB=$TARGET_RANLIB && \
echo "Building zlib" && \
VERS=1.2.13 && \
CHECKSUM=b3a24de97a8fdbc835b9833169501030b8977031bcb54b3b3ac13740f846ab30 && \
cd /home/rust/libs && \
curl -sqLO https://zlib.net/fossils/zlib-$VERS.tar.gz && \
echo "$CHECKSUM zlib-$VERS.tar.gz" > checksums.txt && \
sha256sum -c checksums.txt && \
tar xzf zlib-$VERS.tar.gz && cd zlib-$VERS && \
CFLAGS="-O3 -fPIC" ./configure --static --prefix=$TARGET_HOME && \
make -j$(nproc) && make install && \
cd .. && rm -rf zlib-$VERS.tar.gz zlib-$VERS checksums.txt
# The Rust toolchain to use when building our image
ARG TOOLCHAIN=stable
# Install our Rust toolchain and the `musl` target. We patch the
# command-line we pass to the installer so that it won't attempt to
# interact with the user or fool around with TTYs. We also set the default
# `--target` to musl so that our users don't need to keep overriding it
# manually.
# Chmod 755 is set for root directory to allow access execute binaries in /root/.cargo/bin (azure piplines create own user).
#
# Remove docs and more stuff not needed in this images to make them smaller
RUN chmod 755 /root/ && \
if [ `dpkg --print-architecture` = 'armhf' ]; then GNU_TARGET="armv7-unknown-linux-gnueabihf"; else GNU_TARGET=`uname -m`-unknown-linux-gnu; fi && \
export RUSTUP_USE_CURL=1 && \
curl https://sh.rustup.rs -sqSf | \
sh -s -- -y --profile minimal --default-toolchain $TOOLCHAIN --default-host $GNU_TARGET && \
rustup target add $TARGET || rustup component add --toolchain $TOOLCHAIN rust-src && \
rustup component add --toolchain $TOOLCHAIN rustfmt clippy && \
rm -rf /root/.rustup/toolchains/$TOOLCHAIN-$GNU_TARGET/share/
RUN echo "[target.$TARGET]\nlinker = \"$TARGET_CC\"\n" > /root/.cargo/config.toml
# Build std sysroot for targets that doesn't have official std release
ADD Xargo.toml /tmp/Xargo.toml
ADD s390x-unwind.patch /tmp/s390x-unwind.patch
ADD build-std.sh .
RUN bash build-std.sh
ENV RUSTUP_HOME=/root/.rustup
ENV CARGO_HOME=/root/.cargo
ENV CARGO_BUILD_TARGET=$TARGET
ENV CFLAGS_armv7_unknown_linux_musleabihf='-mfpu=vfpv3-d16'
# Build statically linked binaries for MIPS targets
ENV CARGO_TARGET_MIPS_UNKNOWN_LINUX_MUSL_RUSTFLAGS='-C target-feature=+crt-static'
ENV CARGO_TARGET_MIPSEL_UNKNOWN_LINUX_MUSL_RUSTFLAGS='-C target-feature=+crt-static'
ENV CARGO_TARGET_MIPS64_UNKNOWN_LINUX_MUSLABI64_RUSTFLAGS='-C target-feature=+crt-static'
ENV CARGO_TARGET_MIPS64EL_UNKNOWN_LINUX_MUSLABI64_RUSTFLAGS='-C target-feature=+crt-static'
# Expect our source code to live in /home/rust/src
WORKDIR /home/rust/src
项目配置
在我们项目的根目录下面搭建一个文件,里面配置我们需要的相关信息
创建 Dockerfile 文件
javascript
Dockerfile
# 使用官方 Node.js 运行时作为基础镜像
FROM node:18-alpine
# 设置工作目录
WORKDIR /app
# 复制 package.json 和 package-lock.json
COPY package*.json ./
# 安装项目依赖
RUN npm install
# 复制项目源代码
COPY . .
# 暴露应用端口(根据你的应用修改)
EXPOSE 3000
# 运行应用的命令(根据你的入口文件修改)
CMD ["node", "app.js"]
创建.dockerignore文件
javascript
node_modules
npm-debug.log
.git
.gitignore
README.md
.env
4、打包部署
接下来我们使用docker打包部署node项目
打包之前需要安装一下我们对应的依赖镜像,我的node版本如下。对应的版本我们可以在对应的部分查看
javascript
22.16.0
对应的镜像地址
https://mirrors.aliyun.com/nodejs-release/v22.16.0/?spm=a2c6h.25603864.0.0.52b3773fkunQPT
配置镜像源
javascript
{
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://mirror.ccs.tencentyun.com",
"https://mirrors.aliyun.com",
"https://mirrors.huaweicloud.com/repository/docker-ce",
"https://docker.xuanyuan.me",
]
}
完整的配置如下,配置好了这个时候打包已经可以了
javascript
{
"builder": {
"gc": {
"defaultKeepStorage": "20GB",
"enabled": true
}
},
"experimental": false,
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://mirror.ccs.tencentyun.com",
"https://mirrors.aliyun.com",
"https://mirrors.huaweicloud.com/repository/docker-ce",
"https://docker.xuanyuan.me",
"https://mirrors.tuna.tsinghua.edu.cn/docker-ce"
]
}
根目录下面运行这个打包命令
javascript
// 打包
docker build -t nexus-node-app .
这个时候我们耐心等待一会然后打包就成功了
javascript
// 本地导出打包的文件
docker save -o nexus-node-api.tar nexus-node-api
这个时候在我的根目录下面已经有一个文件了,直接把这个文件丢到我们想要的node服务器即可
nexus-node-api.tar
镜像传输到服务器上
接下来我们将已经打包好的项目直接放到docker服务器上进行运行
方法(2种)
可以直接传送上去或者利用命令行工具直接将我们的项目传递上去
javascript
// 使用 scp 或其他文件传输工具:
scp my-node-app.tar user@your-server-ip:/home/user/
javascript
// 登录服务器,进入你上传文件的目录,执行:
docker load -i nexus-node-api.tar
运行容器
在服务器上进行运行
javascript
docker run -d \
--name my-node-app-container \
-p 80:3200 \
--restart unless-stopped \
your-registry/my-node-app:v1.0.0
// 这里的执行命令为
docker run -d \
--name nexus-node-api \
-p 3200:3200 \
-e NODE_ENV=production \
nexus-node-api:latest
查看我们容器的运行状态
javascript
// 查看容器是否成功运行
docker ps
// 查看容器日志
docker logs nexus-node-api
// 实时查看日志
docker logs -f nexus-node-api
// 停止容器
docker stop nexus-node-api
// 重启容器:
docker restart nexus-node-api
// 删除容器(需要先停止):
docker rm nexus-node-api
这个时候我已经可以看到我的项目运行以及日志了
javascript
// docker logs nexus-node-api
版本号nexus V0.0.1
${author}热烈欢迎你访问Node后端服务器
初始化ws
WebSocket 服务器已启动,监听端口 3000
初始化ws聊天室
ws聊天已启动,监听端口 3001
Server is running on http://0.0.0.0:3200
数据库连接成功😊,我是林太白
打包node项目提示处理
这个时候提示我们
javascript
=> ERROR [internal] load metadata for docker.io/library/node:18-alpine 21.1s
------
> [internal] load metadata for docker.io/library/node:18-alpine:
------
Dockerfile:2
--------------------
1 | # 使用官方 Node.js 运行时作为基础镜像
2 | >>> FROM node:18-alpine
3 |
4 | # 设置工作目录
--------------------
ERROR: failed to build: failed to solve: node:18-alpine: failed to resolve source metadata for docker.io/library/node:18-alpine: failed to do request: Head "https://registry-1.docker.io/v2/library/node/manifests/18-alpine": dialing registry-1.docker.io:443 container via direct connection because disabled has no HTTPS proxy: connecting to registry-1.docker.io:443: dial tcp 108.160.161.83:443: connectex: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
View build details: docker-desktop://dashboard/build/desktop-linux/desktop-linux/ste681kfzh01gt53di0y8ii61
处理解决
这个时候大多数都是配置和镜像的问题,这里我换成了清华镜像站,然后重新部署了一下就ok了