我知道这是一个老问题,但我遇到了完全相同的问题,我花了一段时间才解决。希望这对来自搜索引擎的人有所帮助。
我找到了 2 个解决方案(我最终选择了第二个)。两者都允许您在 docker 中使用环境变量来配置您的 API URL。
解决方案 1(“客户端”端):env.js 资产 + sed
这个想法是让你的 Angular 客户端从你的 HTTP 服务器加载一个env.js 文件。这个env.js 将包含 API URL,并且可以在容器启动时进行修改。这就是你在问题 cmets 中讨论的内容。
在您的 Angular 应用资产文件夹中添加一个 env.js(src/assets 对我来说使用 angular-cli):
var MY_APP_ENV = {
apiUrl: 'http://localhost:9400',
}
在您的index.html 中,您将加载您的环境:
<head>
<meta charset="utf-8">
<base href="/">
<script src="env.js"></script>
</head>
在你的 environment.ts 中,你可以使用变量:
declare var MY_APP_ENV: any;
export const environment = {
production: false,
apiUrl: MY_APP_ENV.apiUrl
};
在你的 NGINX Dockerfile 中做:
FROM nginx:1.11-alpine
COPY tmp/dist /usr/share/nginx/html
COPY run.sh /run.sh
CMD ["sh", "/run.sh"]
run.sh 脚本是 sed 魔法发生的地方:
#!/bin/sh
# API
/bin/sed -i "s|http://localhost:9400|${MY_API_URL}|" /usr/share/nginx/html/env.js
nginx -g 'daemon off;'
在您的 Angular 服务中,使用 environment.apiUrl 连接到 API(您需要导入环境,请参阅 Angular 2 文档)。
方案二(纯服务端):nginx proxy config + envsubst
我对以前的解决方案不满意,因为 API URL 需要从主机的角度来看,它不能在我的 docker-compose 设置中使用另一个容器主机名。
所以我想:很多人使用 NGINX 作为代理服务器,为什么不通过这种方式将/api 代理到我的其他容器。
Dockerfile:
FROM nginx:1.11-alpine
COPY tmp/dist /usr/share/nginx/html
COPY frontend.conf.template /etc/nginx/conf.d/frontend.conf.template
COPY run.sh /run.sh
CMD ["/bin/sh", "/run.sh"]
frontend.conf.template:
server {
listen 80;
server_name myserver;
# API Server
location /api/ {
proxy_pass ${MY_API_URL}/;
}
# Main
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri$args $uri$args/ /index.html;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
运行.sh:
#!/bin/sh
# Substitute env vars
envsubst '$MY_API_URL' \
< /etc/nginx/conf.d/frontend.conf.template \
> /etc/nginx/conf.d/default.conf
# Start server
nginx -g 'daemon off;'
envsubt 允许您使用类似 shell 的语法替换字符串中的环境变量。
然后使用/api/xyz 从 Angular 应用程序连接到 API。
我认为第二种解决方案更清洁。 API URL 可以是 docker-compose 设置中的 API docker 容器名称,这很好。客户不参与,它是透明的。但是,它依赖于 NGINX。