【问题标题】:Deploy and customize a VueJs app using Docker and GitlabCI使用 Docker 和 Gitlab CI 部署和自定义 VueJs 应用程序
【发布时间】:2021-07-27 15:36:10
【问题描述】:

我制作了一个 VueJS 应用程序,基本上是一个网站管理应用程序,它允许使用不同的 API 显示/编辑数据。 此应用可使用环境变量 (VUE_APP_XXX) 进行自定义:API 的 url、标题、颜色主题等...大约 30 个变量,但我肯定会在未来添加其他变量。

现在我使用 Gitlab CI 部署我的应用程序,我有这个 Dockerfile(我删除了大部分环境变量以进行澄清):

# build
FROM node:lts-alpine as build-stage
WORKDIR /app
ENV PATH /app/node_modules/.bin:$PATH
COPY package*.json ./
RUN npm install
COPY . .
ARG VUE_APP_API_URL
ARG VUE_APP_DATA_URL
ENV VUE_APP_API_URL $VUE_APP_API_URL
ENV VUE_APP_DATA_URL $VUE_APP_DATA_URL
RUN npm run build

# production
FROM nginx:stable-alpine as production-stage
COPY --from=build-stage /app/dist /usr/share/nginx/html
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx/nginx.conf /etc/nginx/conf.d
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

还有 gitlab-ci.yml :

docker-build:
  # Official docker image.
  image: docker:latest
  stage: build
  services:
    - docker:dind
  before_script:
    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
  script:
    - |
      docker build --pull 
      --build-arg VUE_APP_API_URL="$CI_TEST_API_URL" 
      --build-arg VUE_APP_DATA_URL="$CI_TEST_DATA_URL" 
      -t "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG" .
    - docker push "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG"
  only:
    - dev
  when: manual

然后在我的服务器上创建一个docker run... 来启动我的应用程序。一切正常,除了:

  • 我必须在 Dockerfile 和 gitlab-ci.yml 中手动指定所有变量
  • 生成的 docker 映像可能包含“敏感”数据,例如登录名和密码
  • 我必须为我的应用的每个实例创建一个图像

出于法律原因,我需要为每个应用创建一个存储库,每个网站创建一个存储库(因为每个存储库可能有不同的所有者)。

所以我的问题是:为许多网站部署此应用程序的许多实例的最佳方法是什么?知道每个网站都需要自己的管理应用程序,可以托管在自己的服务器上。

我是 docker 的新手,我在想:

  • 使用默认环境变量为通用应用创建 docker 映像(可能只使用代码,没有 npm run build 步骤?)
  • 使用这个 docker 镜像为每个实例创建一个容器,使用它自己的环境变量(是否可以使用 docker compose 构建应用程序?)

我对在何处/何时构建 VueJs 应用程序以及为此使用什么工具感到很困惑。 任何帮助表示赞赏,谢谢!

更新: 根据 taleodor 的建议,我发现这个 medium post 似乎可以完成这项工作。我发现它有点“棘手”,但它有效:)

【问题讨论】:

    标签: docker vue.js nginx docker-compose gitlab-ci


    【解决方案1】:

    当你有一个 docker 镜像然后部署它时,每个工具都有一种方法来覆盖烘焙到镜像本身中的环境变量。

    因此,对于您的示例,您可以使用普通的 docker

    docker run -e VUE_APP_API_URL=http://my.url ... 
    

    这实际上会覆盖先前在容器上设置的 VUE_APP_API_URL 变量。同样,任何编排平台(docker compose、swarm、kubernetes 等)都具有覆盖环境变量的能力,因为这是一种非常常见的场景。

    我使用的常用方法 - 使用最通用的值在图像中预填充环境变量,然后在实际部署中覆盖它们 - 然后你不需要很多图像(同一事物的许多图像将是反模式)。

    如果您有更多问题 - 随时加入我们的社区 discord,您可以在那里问我 - https://discord.gg/UTxjBf9juQ

    更新(在下面的评论之后):对于带有编译的 UI 代码的静态图像,算法是运行一些入口点脚本来替换编译的文件。示例可行的模式如下(您可能需要调整才能正确完成,但这给出了想法):

    假设您使用 nginx 作为基础映像,请创建如下所示的 entrypoint.sh 文件(请参阅此 SO 以获取一些参考:Can envsubst not do in-place substitution?):

    #!/bin/sh
    find /usr/share/nginx/html/*.js -type f -exec sh -c "cat {} | envsubst | tee {}.tmp && mv {}.tmp {}" \;
    nginx -g 'daemon off;'
    
    1. 将此 entrypoint.sh 文件复制到您的 docker 映像中,并与 ENTRYPOINT 指令一起使用。

    【讨论】:

    • 嗯,覆盖docker run中的变量对我不起作用...我猜是因为docker镜像包含vuejs应用程序的编译版本,所以vuejs应用程序没有再次编译在运行时?因此为变量指定新值无效(它将如何替换“已编译”js 中的值?)
    • 好点,更新了答案 - 需要你做一些工作才能做到这一点,但给出了这个想法。
    • 感谢您的建议,我找到了在原始帖子中编辑的方法!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-01
    • 2017-07-29
    • 2017-05-21
    • 2017-05-06
    相关资源
    最近更新 更多