- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我需要找到一种动态部署 Angular 应用程序的方法,以便同一个 docker 镜像允许我进行多个部署(开发、暂存、生产),其中修改了访问 URL。
我正在使用 Angular-cli 6.4.1 在 Angular 7 中创建一个应用程序。对于部署,我正在创建一个 docker 多阶段容器,我在其中构建图像并使用 nginx 配置它。
问题是,对于部署,我们使用私有(private)注册表,其中我们使用处理重定向的代理,因此我的应用程序将按照以下方案部署:{SERVER_HOST} : {PORT}/{SERVER_LOCATION}
当我尝试访问该 URL 时,只有 index.html 被加载,因为其余资源与基本路径“/”相关联。
Angular 在构建 (--base-href) 中提供了一个参数,允许修改整个应用程序的路径,但是它对我没有帮助,因为我需要相同的 Docker 镜像来允许我执行不同的部署,以便{SERVER_LOCATION} 参数并不总是相同的。
我也尝试过在运行时读取环境变量来修改 base 标签的 href 属性,但是很难执行未在索引旁边加载的文件中的代码。
作为解决方法,我决定在索引中创建一个函数来执行收集配置参数的 ajax 请求,以便加载其余资源,但我不喜欢它,因为它会破坏 Angular 的操作。
<-- This is working fine, but is not dynamic: -->
npm run build -- --prod --base-href https://myHost.net:8080/path/app/ --configuration=$configuration
<-- And this is working but is not Angular friendly -->
/** assets/data/appConfig.json */
{
"SERVER_HOST": "https://myHost.net:8080",
"SERVER_PATH": "/path/app/"
}
/** index.html */
<script>
(function() {
if (window.onerror) {
loadConfig();
}
function loadConfig() {
var xhttp = new XMLHttpRequest();
var url = 'assets/data/appConfig.json';
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var data = JSON.parse(this.response);
window.appBaseHref = data.SERVER_PATH;
document.getElementById("base").href = data.SERVER_PATH;
}
};
xhttp.open('GET', url);
xhttp.send();
}
})()
</script>
有人告诉我有跳代理的选项,但我找不到办法,我不知道如何配置它。我认为也许可以在 nginx 配置文件中进行某种调整,以便应用程序从提供的 URL 中“读取”并且应用程序的基本 href 始终保持为“/”。
目前我的 nginx.conf 文件是:
server {
listen 80;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html =404;
}
location /documentation {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /documentation/index.html =404;
}
}
位置路径“/”是我的 Angular 应用程序,位置路径“/documentation”是项目文档的保留路径。
我们欢迎任何形式的帮助。
<--- 编辑 --->
这些天我一直在尝试几件事,事实是我对如何继续感到很困惑,因为似乎没有任何效果。
我已经配置 Nginx 来添加 env $uri+$basepath 属性,但我意识到这种关系恰好相反。我需要我的 index.html 向代理路由而不是路径 '/' 发出请求,因为由于这个原因,请求甚至没有进入日志(代理没有重定向我,因为它没有我的前缀应用程序)
我举个例子:我的应用程序托管在:myHost:8080/myapp/front当我输入此 url(myHost:8080/myapp/front) 时,应用程序加载索引,但未加载相关资源(样式、运行时、polyfill、脚本和 main),因为它们将请求发送到:myHost:8080/{resourcePath} 而不是 myHost:8080/myapp/front/{resourcePath}
此时我不知道该何去何从。我将能够得到我想要放置标志 --base-href/myapp/front 的结果,但我希望这条路线是动态的并且取决于我的 VIRTUAL_HOST 系统的环境变量,这当然我不知道在构建应用程序时
接下来我粘贴我的 dockerfile 和 nginx 配置文件。
Dockerfile(注释行是未按预期方式工作的提案)。
### STAGE 0: Based on Node.js, to build and compile Angular ###
FROM node:alpine as node
# Create app directory
WORKDIR /app
# Copy the dependencies to install once and let Docker use the cache for the next builds
COPY package*.json /app/
# Install all dependencies
RUN npm install
# Copy all the project into the image
COPY ./ /app/
# Argument to build the image according to the environment
ARG configuration=production
# Compiles our project
RUN npm run build -- --prod --configuration=$configuration
### STAGE 1: Based on Nginx, to have only the compiled app, ready for production with Nginx ###
FROM nginx:1.13.3-alpine
## Remove default nginx website
RUN rm -rf /usr/share/nginx/html/*
## From 'builder' stage copy over the artifacts in dist folder to default nginx public folder
COPY --from=node /app/dist/dsa-frontend /usr/share/nginx/html
# Add directive
# COPY nginx-custom.conf.template /etc/nginx/conf.d/default.conf.template
COPY nginx-custom.conf /etc/nginx/conf.d/default.conf
# CMD /bin/bash -c "envsubst '\$VIRTUAL_SERVICE_LOCATION' < nginx-custom.conf > /etc/nginx/conf.d/default.conf"
CMD ["nginx", "-g", "daemon off;"]
nginx-custom.conf
server {
listen 80;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /myapp/front$uri /myapp/front$uri/;
# try_files $uri $uri/ $uri$VIRTUAL_SERVICE_LOCATION $uri$VIRTUAL_SERVICE_LOCATION/ /index.html;
}
location /documentation {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /documentation/index.html =404;
}
}
但这一切似乎都不起作用。
最后,我们决定从代理中删除开发并打开一个新端口来部署此应用程序,因此根路径现在是“/”。
现在一切正常。
最佳答案
我认为我设法获得了针对完全相同问题的全面解决方案(尽管可能相当脆弱 - 请随时提出改进建议!):为多个环境重用一个 Angular/NGINX Docker 镜像(因此多个基本路线)。
此外,我想解决访问外部 API 的问题,因此应用程序请求的所有内容都将通过容器中的 NGINX,因此您不必考虑 CORS .在我的示例中,我有两件事:
客户端路由按预期工作,ROOT_PATH
对应于 /
。
我仍然没有尝试(但我打算)的事情:
最终结果是这样的:
在本地构建和运行容器(一旦一切就绪)
ROOT_PATH
是您要查找的参数。
proxy_pass
,需要
DNS_IP
,您可能需要 substitute Google DNS with something else .
docker build . -t fancy-web-app && \
docker run -it --rm \
--name fancy-web-app-configured \
--publish target=80,published=80 \
--env ROOT_PATH='staging' \
--env WEBSOCKET_PATH='socket.io' \
--env IMAGE_PATH='image' \
--env API_URL='http://api.server.example.com/api/v1/' \
--env DNS_IP='8.8.8.8 8.8.4.4' \
fancy-web-app
为了清楚起见,我将列出所有你需要的东西:
NGNIX
nginx.conf
在容器启动期间修改,否则无法使用,因为它引用了环境变量。
docker
docker-entrypoint.sh <-- * * * 这就是魔法发生的地方。 * * *
Dockerfile
Multistage , 默认有 docker-entrypoint.sh
entrypoint用于运行时阶段。
Angular
index.html
默认开发配置,在容器启动时修改,变成“运行时配置”。
app.conf.ts
配置允许您抽象出全局变量中的配置,而不是将这种丑陋进一步带入您的服务
app.module.ts
Angular 依赖注入(inject)允许您在任何服务中引用配置
some-angular.service.ts
这是您使用注入(inject)配置的地方。
Angular 加分
proxy.conf.json
用于在没有容器的本地主机上工作(相当于用于开发的 nginx.conf,将由 WebPack/ng serve
使用)
angular.json
在这里您可以指定一次代理配置,默认情况下到处都有它。
如果有兴趣,我可以设置 GitHub 存储库,其中包含所有需要的部分(请评论/评分,这样我就可以看到有必要这样做)。
NGINX
<强>1。 nginx.conf
server {
listen 80;
# Serve static files (HTML, CSS, JS)
location /${ROOT_PATH} {
# Using `alias` insead of `root` directive, so ${ROOT_PATH}
# will be discarded and static file will be fetched straight
# from the specified folder
alias /usr/share/nginx/html;
try_files $uri $uri/ /index.html =404;
}
# Re-route calls to external APIs
location ~ ^/${ROOT_PATH}/(${WEBSOCKET_PATH}|${IMAGE_PATH})/(.*) {
resolver ${DNS_IP};
proxy_pass ${API_URL}/$1/$2$is_args$args;
proxy_http_version 1.1;
proxy_cache_bypass $http_upgrade;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
}
}
docker
<强>2。 docker-入口点.sh
#!/usr/bin/env sh
set -eu
# Inject environment variables into NGINX configuration
# List all variables to be substituted to avoid clashing with
# NGINX own variables: https://serverfault.com/questions/577370
envsubst \
'${API_URL} \
${ROOT_PATH} \
${WEBSOCKET_PATH} \
${IMAGE_PATH} \
${DNS_IP}' \
< /etc/nginx/conf.d/default.conf.template \
> /etc/nginx/conf.d/default.conf
cat /etc/nginx/conf.d/default.conf
# Set correct HTML base tag, so static resources are fetched
# from the right path instead of the root path.
# NOTE: Trailing and leading slashes in base href are important!
# Using `~` separator to avoid problems with forward slashes
sed --in-place \
's~<base href="/">~<base href="/'$ROOT_PATH'/">~' \
/usr/share/nginx/html/index.html
# Set WebSocket API endpoint
# Using `~` separator to avoid problems with forward slashes
sed --in-place \
"s~webSocketPath.*,~webSocketPath: \`/$ROOT_PATH/$WEBSOCKET_PATH\`,~" \
/usr/share/nginx/html/index.html
# Set image API endpoint
# Using `~` separator to avoid problems with forward slashes
sed --in-place \
's~imageBaseUrl.*~imageBaseUrl: `${window.location}'$IMAGE_PATH'`~' \
/usr/share/nginx/html/index.html
cat /usr/share/nginx/html/index.html
exec "$@"
<强>3。 Dockerfile
# Produce static files
FROM node:10.15.3-alpine
WORKDIR /app
COPY ./package.json ./package.json
COPY ./package-lock.json ./package-lock.json
RUN npm set progress=false && \
npm install --silent
COPY . /app
RUN npm run ng build -- --prod --output-path=dist
# Use NGINX to serve static files and re-route requests
FROM nginx:1.15.10-alpine
RUN rm -rf /usr/share/nginx/html/*
COPY --from=0 /app/dist/ /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf.template
COPY docker-entrypoint.sh /
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD [ "nginx", "-g", "daemon off;" ]
EXPOSE 80
Angular
<强>4。 index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Fancy web app</title>
<base href="/">
<script>
// These default values make sense when you `npm start`
// They will be substituted during container startup
// Using global variable on the window object here.
// Is there a better way?
window['app-config'] = {
webSocketUrl: `${window.location.host}`,
webSocketPath: `/socket.io`,
imageBaseUrl: `${window.location}image`
};
console.log(window['app-config']);
</script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<pdd-root></pdd-root>
</body>
</html>
<强>5。应用程序.conf.ts
import { Injectable } from '@angular/core';
@Injectable()
export class Configuration {
webSocketUrl: string;
webSocketPath: string;
imageBaseUrl: string;
}
// Reading configuration out, so we have it Angular world
export const AppConfiguration: Configuration = window['app-config'];
6. app.module.ts(剪掉不感兴趣的细节)
import <--snip-->
@NgModule({
declarations: [
<--snip-->
],
imports: [
<--snip-->
],
providers: [
<---snip-->
SomeAngularService,
{ provide: Configuration, useValue: AppConfiguration },
<---snip--->
],
bootstrap: [AppComponent]
})
export class AppModule { }
7. some-angular.service.ts(删除了不感兴趣的细节)
<--snip-->
export class BackendService {
constructor(private configuration: Configuration) {
const client = io(
// Do not append route to the hostname
// otherwise Socket.IO will treat it as `namespace`
this.configuration.webSocketUrl,
{
// Do not auto-connect to exclude racing
// between setup and connection
autoConnect: false,
// You have to specify route here
path: configuration.webSocketPath
});
<--snip-->
Angular 加分
<强>8。 proxy.conf.json
{
"/socket.io/*": {
"target": "http://localhost:3000/socket.io/",
"ws": true,
"secure": false,
"logLevel": "debug",
"pathRewrite": { "^/socket.io" : "" }
},
"/image/*": {
"target": "http://localhost:3000/image/",
"secure": false,
"logLevel": "debug",
"pathRewrite": { "^/image" : "" }
}
}
<强>9。 angular.json -> 查看下方截图之前的最后一行
<--snip-->
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "fancy-web-app:build",
"proxyConfig": "proxy.conf.json"
<--snip-->
关于angular - 动态部署 Angular。一个docker镜像,多个部署,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54478335/
我在 *.sql 文件中得到了我的数据库转储(表、函数、触发器等)。此时我正在通过 jenkins 部署它们,通过传递执行 shell 命令: sudo -u postgres psql -d my_
我正在使用网络部署 API 来部署网络包(.zip 文件,由 MSDeploy.exe 创建)以编程方式将包发布到服务器(在发布包之前我们需要做一些其他事情这就是为什么我们不使用 MSDeploy.e
我们正在使用 Web Deploy 3 的(几乎完全未记录的)“公共(public) API”来创建我们网站的 .zip 包,然后将其同步到服务器: DeploymentBaseOptions des
将 clojure 应用程序制作成可执行文件的最简单方法是什么,例如 http://rawr.rubyforge.org/ ruby 吗? (exe 和 app 文件也是) 最佳答案 使用 leini
是否可以下载 Android 源代码并针对任何设备进行编译? 我想做的是尝试 GSM 代码部分并编译操作系统并将其部署到我的摩托罗拉手机上。 谢谢! 最佳答案 是的,但这很难,因为大多数手机不共享驱动
我正在考虑用 c/c++ 编写需要在大多数个人计算机上运行的 nbody 样式模拟。本质上是一个 O(n^2) 粒子模拟器。 因为这需要相当用户友好,所以我希望有 1 个不需要用户安装任何东西的 Wi
需要了解 kubernetes 部署中 kube_deployment_status_replicas 和 kube_deployment_spec_replicas 指标的区别 最佳答案 简而言之,
我正在尝试使用分类器部署 Maven Artifact 。由于我需要源代码和 JAR(我从 GWT 使用它),我想获得 artifact-version-classifier.jar 和 artifa
我设置部署以将我的项目代码与存储我的网站的 FTP 服务器上的项目同步。 但是,每次尝试同步时,我总是必须登录。 我什至检查了记住,但它不起作用! 我正在使用最新的 PhpStorm 2017.1.4
我在 Visual Studio 2008 中开发了一个 ASP.NET 网站。现在我想在其他机器上部署它。我怎样才能做到这一点??就像我们为 Windows 应用程序制作安装包一样,我们可以为 AS
将 QT 框架添加到我的 .app 包中 我正在关注 Qt 站点上关于部署的文档。 我创建了一个名为 HTTPClient.app 的应用程序 我在 Contents 下创建了 Framework 文
这个问题不太可能对任何 future 的访客有帮助;它只与一个小的地理区域、一个特定的时间点或一个非常狭窄的情况相关,通常不适用于互联网的全局受众。如需帮助使这个问题更广泛适用,visit the h
我正在研究改变我目前创建营销网站的策略。目前,我完全用 PHP 从头开始构建网站,使用一个简单的包含系统。所有代码(以及内容)都存储在文件(而不是数据库)中,允许我使用 Subversion 进行
我有一个长期运行的服务(在 while 1 循环中)并通过 GCloud pub/sub 处理有效负载,之后它将结果写入数据库。 该服务不需要监听任何端口。 Kind=Deployment 的声明性
似乎部署已停滞不前。我该如何进一步诊断? kubectl rollout status deployment/wordpress Waiting for rollout to finish: 2 ou
我正在Dart中使用前端的Angular和后端的Shelf构建一个客户端/服务器应用程序。当我执行pub build时,它会按预期生成Dart文件的javascript,但不会替换HTML文件中的Da
我在 Azure 部署中心的下拉列表中看不到我的所有 Github 组织存储库。 Azure 很久以前就已经被授权了,下拉列表正确地显示了所有的存储库,直到上周我在 DevOps 中玩游戏时,不得不再
我认为标题几乎说明了一切...对于 Deployd 来说是全新的,所以任何关于如何最好地实现这一点的指示都值得赞赏。 最佳答案 要获取用户创建的集合中的对象(我假设您使用的是 javascript 库
我有一个试图用于CD服务器的部署脚本,但是在编写bash脚本以完成一些所需的步骤(例如运行npm和迁移命令)时遇到了问题。 我将如何从该脚本进入容器bash,运行下面的命令,然后退出以完成对更改的提取
我想在使用 kubectl 时将参数传递给 Kubernetes 部署命令应用部署文件。 示例:在我的部署 .yaml 中,我有如下参数,我想在使用 kubectl apply - f .yaml 运
我是一名优秀的程序员,十分优秀!