如何使用Docker动态地将环境变量分配给角度cli项目?

Man*_* PV 9 docker angular-cli

我正在使用角度cli项目和节点项目运行两个单独的docker容器.

这是我的Dockerfile

### STAGE 1: Build ###

# We label our stage as 'builder'
FROM node:carbon as builder

COPY package.json package-lock.json ./

RUN npm set progress=false && npm config set depth 0 && npm cache clean --force

## Storing node modules on a separate layer will prevent unnecessary npm installs at each build
RUN npm i && mkdir /ng-app && cp -R ./node_modules ./ng-app

WORKDIR /ng-app

COPY . .

## Build the angular app in production mode and store the artifacts in dist folder
RUN $(npm bin)/ng build --aot --build-optimizer --environment=test

### STAGE 2: Setup ###

FROM nginx:1.13.3-alpine

## Copy our default nginx config
COPY nginx/default.conf /etc/nginx/conf.d/

## 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=builder /ng-app/dist /usr/share/nginx/html

CMD ["nginx", "-g", "daemon off;"]
Run Code Online (Sandbox Code Playgroud)

节点容器URL存储在environment.ts(angular)中.

Environment.ts文件

declare var require: any;
const pack = require('../../package.json');

export const environment = {
  production: false,
  API_URL: 'http://localhost:3000/',
  socket: 'http://localhost:3200',
  appName: pack.name,
  version: pack.version,
  envi: 'test'
};
Run Code Online (Sandbox Code Playgroud)

在角度项目的构建时间期间获取节点API_URL.但我想在docker run命令期间修改环境变量.(即)我想在docker容器运行时期间动态地将环境变量值添加到environment.ts文件中

例如,docker run -e API_URL = 192.168.10.147:3000 -p 4200:80 --name = angular angular_image

我怎样才能做到这一点?

chr*_*hrx 15

我将尝试总结我与开发Angular应用程序的同事一起解决的解决方案,以解决这个问题.为了更好地说明解决方案,我首先描述了角应用程序的dev文件夹树(文件夹名称在方括号中),其中每个相关元素如下所述:

+---[my angular cli project]
¦   ¦
¦   +---[src]
¦   ¦   +---[assets]
¦   ¦   ¦   +---[json]
¦   ¦   ¦   ¦   +---runtime.json
¦   ¦   ¦   ¦  
¦   ¦   ¦   ..other angular application assets files ...
    ¦   ¦   
¦   ¦   ...other angular application source files...
¦   ¦
¦   +---[dist]
¦   ¦   ...built angular files
¦   ¦
¦   +---[docker]
¦   ¦   +---[nginx]
¦   ¦   ¦   +---default.conf
¦   ¦   +---startup.sh
¦   ¦
¦   +---Dockerfile
¦
... other angluar cli project files in my project ...
Run Code Online (Sandbox Code Playgroud)

在angular cli项目中,需要在运行时使用环境变量的值替换的配置数据保存在应用程序资产的静态json文件中.我们选择在此处找到它assets/json/runtime.json.在此文件中,要替换的值的处理方式${API_URL}与以下示例中的变量类似:

./src/assets/json/runtime.json:

{
  "PARAM_API_URL": "${API_URL}"

  ...other parameters...
}
Run Code Online (Sandbox Code Playgroud)

在运行时,角度代码将读取PARAM_API_URL此文件的值,该文件的内容将在运行时使用环境值进行修改,如下所述.从技术上讲,json是由一个Angular服务通过http读取的,也就是说,Web应用程序对上面的静态资产json文件的URL执行HTTP GET操作.

@Injectable()
export class MyComponent {

    constructor( private http: Http ) {
    }

    ...

    someMethod() {

        this.http.get( 'assets/json/runtime.json' ).map( result => result.PARAM_API_URL ).subscribe( 
            api_url => {
                ... do something with the api_url 
                eg. invoke another http get on it ...
            }
        );
      }

}
Run Code Online (Sandbox Code Playgroud)

要创建一个在运行时启动时执行环境替换的docker容器,startup.sh将在其中放入一个脚本(见Dockerfile下文),在启动nginx Web服务器之前,容器启动时会在上面的文件中执行一个evnsubst:

./docker/startup.sh:

echo "Starting application..."
echo "API_URL = ${API_URL}"
envsubst < "/usr/share/nginx/html/assets/json/runtime.json" > "/usr/share/nginx/html/assets/json/runtime.json"
nginx -g 'daemon off;'
Run Code Online (Sandbox Code Playgroud)

如下所示,Dockerfile执行以下操作:在复制已编译的角度文件后./dist,然后将startup.sh脚本定义为CMD起点(主机 /dist文件夹为COPYed /usr/share/nginx/html,这就是为什么这是用于定位runtime.json的路径)上面的envsubst调用中提到的文件).请注意,与Dockerfile不同,这里我们不包括角度cli源的构建阶段,而是ng build应该由开发人员在容器映像创建之前执行 - 并且此类构建的结果预计会在./dist文件夹中找到.但是,对于手头问题的解决方案而言,这是一个微小的差异.

./Dockerfile:

FROM nginx:1.13.3-alpine

## Copy our default nginx config
COPY docker/nginx/default.conf /etc/nginx/conf.d/

## Remove default nginx website
RUN rm -rf /usr/share/nginx/html/*

## copy over the artifacts in dist folder to default nginx public folder
COPY dist /usr/share/nginx/html

## startup.sh script is launched at container run
ADD docker/startup.sh /startup.sh
CMD /startup.sh 
Run Code Online (Sandbox Code Playgroud)

现在,当您构建容器时,可以使用以下命令运行它:

docker run -e "API_URL=<your api url>" <your image name> 
Run Code Online (Sandbox Code Playgroud)

在启动nginx之前,将在runtime.json中替换给定的值.

为了完整性,虽然与特定问题无关,但我还包括docker/nginx/default.conf配置nginx实例的文件

./docker/nginx/default.conf:

server {

  listen 80;

  sendfile on;

  default_type application/octet-stream;

  gzip on;
  gzip_http_version 1.1;
  gzip_disable      "MSIE [1-6]\.";
  gzip_min_length   256;
  gzip_vary         on;
  gzip_proxied      expired no-cache no-store private auth;
  gzip_types        text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;
  gzip_comp_level   9;

  root /usr/share/nginx/html;

  location / {
    try_files $uri $uri/ /index.html =404;
  }

}
Run Code Online (Sandbox Code Playgroud)