You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在不丢失数据的情况下更新Docker容器内服务端应用代码

问题场景

我有一个Docker Compose项目,文件结构如下:

.
|-- .dockerignore
|-- Dockerfile
|-- docker-compose.yml
|-- messages
    |-- 20221120-010625.txt
    |-- 20221120-010630.txt
    `-- 20221120-010641.txt
|-- package.json
`-- server.js

执行docker-compose up -d启动后,能通过http://localhost/?message=<message>在服务器上记录消息。现在需要更新源码(比如给页面里的Created file ...文本加###前缀),但绝对不能丢失已有的消息数据。

之前试过docker-compose down --volumes && docker-compose up -d --force-recreate --build,源码是更新了,但所有消息全没了;后来尝试在docker-compose.yml里给/var/www/html/messages挂载命名卷,结果卷目录归root所有,node用户没权限写入,直接报错。

解决方案

1. 搞定命名卷的权限问题

Docker创建命名卷时默认用root权限初始化目录,导致node用户写不了,解决方法有两种:

方法一:修改Dockerfile,启动时自动调权限

把Dockerfile里的CMD改成下面这样,启动服务前先确保messages目录权限正确:

FROM node:16-alpine

RUN mkdir -p /var/www/html && chown -R node:node /var/www/html

WORKDIR /var/www/html

COPY --chown=node:node . .

USER node

RUN npm i

EXPOSE 8080

# 替换原来的CMD,先创建目录并改权限再启动服务
CMD ["sh", "-c", "mkdir -p /var/www/html/messages && chown -R node:node /var/www/html/messages && npm run start"]

方法二:手动调整已有命名卷的权限

如果已经创建了命名卷,先跑个临时容器把权限改好:

docker run --rm -v messages:/var/www/html/messages node:16-alpine chown -R node:node /var/www/html/messages

改完再启动应用容器,就能正常写入消息了。

2. 正确的源码更新流程

挂载好命名卷后,更新源码根本不用删卷,直接重新构建镜像并重启容器就行:

# 构建新镜像
docker-compose build
# 用新镜像重启容器,保留卷数据
docker-compose up -d --force-recreate

或者合并成一条命令:

docker-compose up -d --force-recreate --build

⚠️ 重点:别加--volumes参数,加了就会删掉卷里的所有消息!

3. 完善docker-compose.yml配置

确保docker-compose.yml里正确配置命名卷:

version: '3'

services:
  serverapp:
    build:
      dockerfile: Dockerfile
    container_name: serverapp
    restart: unless-stopped
    ports:
      - "80:80"
    volumes:
      - messages:/var/www/html/messages  # 把命名卷挂载到消息存储目录

volumes:
  messages:  # 定义命名卷

4. 验证效果

修改server.js里的响应内容,比如把:

res.send(`<pre>${filesListStr}\nCreated file: "${filePathMessage}" with content: "${message}".</pre>`);

改成:

res.send(`<pre>${filesListStr}\n### Created file: "${filePathMessage}" with content: "${message}".</pre>`);

然后执行更新命令,刷新页面就能看到新的格式,之前的消息文件也都还在。

内容的提问来源于stack exchange,提问作者davidesp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 06:45:33