【Docker】前端基于dockerfiel构建镜像部署,实现在容器启动时传递环境变量, 请求不同服务地址

时间:2024-02-29 18:53:20

前端部署采用 docker 的方式, 实现在容器启动时传递环境变量, 请求不同服务地址

实现思路: 定义.env.xxx 文件(环境变量赋值),在compose.yml中引入.env.xxx 文件,环境变量通过nginx的sub_filter放到html的meta标签里
----------------------------------------------------------【etl-ui.env】--------------------------------------------------------------------

API_REQUEST_ADDRESS=http://xxx.xxx.x.xx:8601

----------------------------------------------------------【compose.yml】--------------------------------------------------------------------

compose.yml中前端容器中添加env_file, 引入环境变量配置文件

version: "6.6"
name: myy-system
services:
  myy-myy-ui-1:
    container_name: myy-myy-ui-1
    image: xxx.xxx.x.xx:8084/myy-app-ui:latest
    restart: unless-stopped
    ports:
      - "8001:8700"
    env_file:
      - etl-ui.env
    deploy:
      resources:
        limits:
          memory: 8G
    environment:
      TZ: Asia/Shanghai
    depends_on:
      - myy-myy-ignite-1

----------------------------------------------------------【entrypoint.sh】--------------------------------------------------------------------
在Dockerfile同级目录下添加entrypoint.sh文件, 获取容器启动时传入的环境变量API_REQUEST_ADDRESS的值保存到变量API_REQUEST_ADDRESS_VAL中

#!/bin/bash

sed -i "s|API_REQUEST_ADDRESS_VAL|${API_REQUEST_ADDRESS}|g" /usr/share/nginx/html/index.html
exec nginx -g 'daemon off;'

----------------------------------------------------------【Dockerfile】--------------------------------------------------------------------
通过nginx的sub_filter放到html的meta: 复制entrypoint.sh,设置执行权限和容器启动入口

COPY entrypoint.sh /

# 设置执行权限
RUN chmod +x /entrypoint.sh

# 设置容器启动时的入口
ENTRYPOINT ["/entrypoint.sh"]

Dockerfile完整代码:

# Stage 1: 构建Node.js应用 
FROM node:16.14.0 AS builder
WORKDIR /app 
RUN npm cache clean —force
COPY package*.json ./
RUN npm install --force --registry=http://119.3.241.212:8088/repository/npm-group
COPY . .
RUN npm run build:sit

# Stage 2: 构建Nginx镜像
FROM nginx:latest
WORKDIR /usr/share/nginx/html

# 将Node.js应用构建结果复制到Nginx镜像中
COPY --from=builder /app/dist/ .

# 可选:复制Nginx配置文件
COPY nginx.conf /etc/nginx/nginx.conf

# 暴露端口
EXPOSE 8700

COPY entrypoint.sh /

# 设置执行权限
RUN chmod +x /entrypoint.sh

# 设置容器启动时的入口
ENTRYPOINT ["/entrypoint.sh"]

----------------------------------------------------------【nginx.conf】--------------------------------------------------------------------

user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    gzip_static on;
    gzip_proxied        expired no-cache no-store private auth;
    gzip_disable        "MSIE [1-6]\.";
    gzip_vary           on;
    gzip  on;
    gzip_min_length 1k;
    gzip_buffers 4 16k;
    gzip_comp_level 9;

    gzip_types text/plain application/javascript application/css  text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
    client_max_body_size 20m;

    server {
        listen       8700;
        listen  [::]:8700;
        server_name  localhost;
        location / {
            root   /usr/share/nginx/html;
            index  index.html index.htm;
            try_files $uri $uri/ /index.html;
        }
        # 静态资源地址 (其中 /myy/myy-server/  为上下文)
        location ~* ^/myy/myy-server/(.*)$ {
            rewrite ^/myy/myy-server/(.*)$ /$1 last;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }

    }
}

----------------------------------------------------------【index.html】--------------------------------------------------------------------
public目录下的index.html
添加 <meta content="API_REQUEST_ADDRESS_VAL" name="API_REQUEST_ADDRESS" />, 存储容器启动时传入的环境变量API_REQUEST_ADDRESS_VAL

<!DOCTYPE html>
<html lang="zh-cmn-Hans">
  <head>
    <meta charset="utf-8" />
    <meta content="IE=edge" http-equiv="X-UA-Compatible" />
    <meta content="webkit" name="renderer" />
    <meta
      content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
      name="viewport"
    />
    <link href="<%= BASE_URL %>favicon.ico" rel="icon" />
    <link
      href="<%= BASE_URL %>static/css/loading.css?random=<%= VUE_APP_RANDOM %>"
      rel="stylesheet"
    />
    <title><%= VUE_APP_TITLE %></title>
    <meta
      content="myy管理系统"
      name="keywords"
    />
    <meta content="<%= VUE_APP_AUTHOR %>" name="author" />
    <meta content="API_REQUEST_ADDRESS_VAL" name="API_REQUEST_ADDRESS" />

    <% if (process.env.NODE_ENV !== 'development') { %>
    <script src="<%= BASE_URL %>static/js/web-report-vue.min.js"></script>
    <!-- <script type="text/javascript">
      window.Performance({
        domain: `<%= VUE_APP_PERFORMANCE %>/api/v1/report/web`,
        add: {
          appId: `<%= VUE_APP_PERFORMANCE_APP_ID %>`
        }
      });
    </script> -->
    <% }
    %>

  </head>
  <body>
    <noscript></noscript>
    <div id="app">
      <div class="first-loading-wrp">
        <div class="loading-wrp">
          <span class="dot dot-spin">
            <i></i>
            <i></i>
            <i></i>
            <i></i>
          </span>
        </div>
        <h1><%= VUE_APP_TITLE %></h1>
      </div>
    </div>
  </body>
  <script type="text/javascript">
    (function () {
      var ua = navigator.userAgent.toLocaleLowerCase();
      var browserType = "",browserVersion = "";
      if (ua.match(/msie/) != null || ua.match(/trident/) != null) {
        browserType = "IE";
        browserVersion =ua.match(/msie ([\d.]+)/) != null? ua.match(/msie ([\d.]+)/)[1]: ua.match(/rv:([\d.]+)/)[1];
        if (1 * browserVersion < 12) {
          document.body.innerHTML = "<p>请在Chrome浏览器上使用系统</p>" +
            "<p><a href='https://www.google.cn/intl/zh-CN/chrome/' target='_blank'>点击下载</a></p>";
        }
      }
    })();
  </script>
</html>

----------------------------------------------------------【服务请求】--------------------------------------------------------------------
axios请求服务时拿到meta标签content 属性里面存储的API_REQUEST_ADDRESS_VAL的值,即为需要请求的后台服务地址

const CUSTOM_API_REQUEST_ADDRESS = document.querySelector('meta[name="API_REQUEST_ADDRESS"]')?.getAttribute('content')
const API_CONTEXT = '/myy/myy-server'
const requestUrl = process.env.NODE_ENV === "development" ? "" : (CUSTOM_API_REQUEST_ADDRESS+API_CONTEXT)
const instance = axios.create({
  baseURL: requestUrl,
  timeout: requestTimeout
  // headers: {
  //   "Content-Type": contentType
  // }
});