PowerShell
Windows
共享文件夹需要管理员权限
进入你的工作文件夹,例如我的工作文件夹为
Set-Location C:\Users\huzh\OneDrive\Angular
git clone https://github.com/huzhenghui/Angular-in-Docker-by-Windows-share-folder.git
Set-Location .\Angular-in-Docker-by-Windows-share-folder
git submodule update --init
1
步:共享Windows
文件夹到Docker
.\step.1.share-windows-folder-to-docker.ps1
输出内容很多,略,结果看下面的测试。
2
步:测试Docker
访问Windows
共享文件夹.\step.2.share-windows-folder-to-docker.test.ps1
如果从输出结果中看到文件夹的内容,就说明共享设置成功了
Angular-App.vscode.launch.json
LICENSE
angular.cli-1.7.3.Dockerfile
docker-compose.yml
node-npm-9.10.0-5.8.0.Dockerfile
share-windows-folder-to-docker
step.1.share-windows-folder-to-docker.ps1
step.2.share-windows-folder-to-docker.test.ps1
step.3.docker-compose.up.ps1
step.4.open.browser.ps1
step.5.open.code.ps1
step.6.docker-compose.down.ps1
step.7.clean.ps1
......
3
步:启动.\step.3.docker-compose.up.ps1
首次启动的时间比较久,以后就快了,详见本文后面的代码详解。
4
步:打开浏览器运行另一个PowerShell
窗口,进入到代码文件夹。
.\step.4.open.browser.ps1
将自动打开浏览器访问该页面。
5
步:使用Visual Studio Code
打开Angular
应用文件夹在第二个PowerShell
窗口中运行。
.\step.5.open.code.ps1
脚本将
Chrome
调试Visual Studio Code
(需要电脑上安装Visual Studio Code
)等Visual Studio Code
启动后测试自动更新
Visual Studio Code
将自动打开Chrome
浏览器(需要电脑上安装Chrome
浏览器)Chrome
浏览器是否自动访问页面src/app/app.component.ts
中的标题名称PowerShell
窗口是否自动更新Chrome
浏览器是否自动刷新6
步:停止在第二个PowerShell
窗口中运行。
.\step.6.docker-compose.down.ps1
观察第一个PowerShell
窗口是否停止服务。
7
步:清理不再使用的时候,可以运行清理脚本
.\step.7.clean.ps1
因为步骤较多,第一次建议从第1
步到第7
步逐步运行一遍,熟悉各步骤。
脚本直接调用docker
、docker-machine
、docker-compose
等命令,
可能在不同安装方式的电脑上有所不同,如果不能使用请反馈。
第7
步清理脚本不清理已经设置的共享文件夹,因此清理后再次运行的时候,
可以直接从第3
步开始。当然也就不需要使用管理员权限启动PowerShell
。
第3
步中首次运行过程较长,很有可能受到网络影响而终止,可以重新运行。
如果重新运行失败,建议使用第7
步清理后再次运行。
第6
步停止后,再次运行第3
步将再次启动,再次启动将自动跳过构建的环节。
第4
步自动通过环境变量获取Docker
主机的IP
地址,然后使用浏览器访问,
如果不能正确打开请手工试试。
第5
步自动通过环境变量获取Docker
主机的IP
地址,
然后生成Visual Studio Code
的调试配置文件,本例采用简单粗暴的方式生成,
不同的Visual Studio Code
版本可能略有不同,
如果不能正确打开调试请手工配置调试试试。
脚本中把node_modules
都扔到了Docker
中,
这样的好处是Windows
上只包含程序相关代码,坏处就是code
找不到这些代码了,
如果需要,可以参照后面的代码说明修改。
下面详细讲解代码。
1
步:共享Windows
文件夹到Docker
.\step.1.share-windows-folder-to-docker.ps1
代码如下
.\share-windows-folder-to-docker\share-windows-folder-to-docker.ps1 -volumeName Angular-in-Docker-by-Windows-share-folder -optCache none
这是一个通用的用于共享Windows
文件夹到Docker
的脚本,参见
https://blog.csdn.net/hu_zhenghui/article/details/79189520
该脚本以git
的submodule
子模块方式引用,因此需要更新子模块代码。
git submodule update --init
脚本中的Windows
共享文件夹需要管理员权限,
因此运行这个脚本的PowerShell
需要管理员权限。
脚本中操作Docker
的部分直接调用docker
、docker-machine
命令,
因此需要PowerShell
中能直接使用这两个命令。
2
步:测试Docker
访问Windows
共享文件夹.\step.2.share-windows-folder-to-docker.test.ps1
代码如下
docker run --rm -v Angular-in-Docker-by-Windows-share-folder:/Angular-in-Docker-by-Windows-share-folder alpine ls /Angular-in-Docker-by-Windows-share-folder
docker volume inspect Angular-in-Docker-by-Windows-share-folder
这里的脚本用于测试之前共享Windows
文件夹到Docker
的脚本。
第一行是在Docker
中访问Windows
共享的文件夹。
第二行是查看Docker
中Volume
卷的设置。
3
步:启动.\step.3.docker-compose.up.ps1
脚本中的代码很简单
docker-compose up
docker-compose
命令将按照docker-compose.yml
启动,代码如下:
version: "3.4"
services:
node-npm-9.10.0-5.8.0:
image: node-npm:9.10.0-5.8.0
build:
context: .
dockerfile: node-npm-9.10.0-5.8.0.Dockerfile
angular.cli-1.7.3:
depends_on:
- node-npm-9.10.0-5.8.0
image: angular.cli:1.7.3
build:
context: .
dockerfile: angular.cli-1.7.3.Dockerfile
ng-new:
depends_on:
- angular.cli-1.7.3
image: angular.cli:1.7.3
volumes:
- type: volume
source: ApplicationRootVolume
target: /ApplicationRoot
- type: volume
source: AngularAppNodeModules
target: /ApplicationRoot/Angular-App/node_modules
- Docker-Compose-Startup-Order:/Startup-Order
command: |
bash -c '
echo ng-new start;
touch /Startup-Order/ng-new.start;
cd /ApplicationRoot;
ng new Angular-App;
echo ng-new done return code = $$?;
touch /Startup-Order/ng-new.done;'
npm-install:
depends_on:
- ng-new
image: angular.cli:1.7.3
volumes:
- type: volume
source: ApplicationRootVolume
target: /ApplicationRoot
- type: volume
source: AngularAppNodeModules
target: /ApplicationRoot/Angular-App/node_modules
- Docker-Compose-Startup-Order:/Startup-Order
command: |
bash -c '
echo npm-install start;
touch /Startup-Order/npm-install.start;
while [[ ! -f /Startup-Order/ng-new.done || /Startup-Order/ng-new.done -ot /Startup-Order/ng-new.start ]]; do sleep 1; done;
echo npm-install doing;
cd /ApplicationRoot/Angular-App;
npm install;
echo npm-install done;
touch /Startup-Order/npm-install.done;'
ng-serve:
depends_on:
- npm-install
image: angular.cli:1.7.3
volumes:
- type: volume
source: ApplicationRootVolume
target: /ApplicationRoot
- type: volume
source: AngularAppNodeModules
target: /ApplicationRoot/Angular-App/node_modules
- Docker-Compose-Startup-Order:/Startup-Order
ports:
- 80:80
command: |
bash -c '
echo ng-serve start;
while [[ ! -f /Startup-Order/npm-install.done || /Startup-Order/npm-install.done -ot /Startup-Order/npm-install.start ]]; do sleep 1; done;
echo ng-serve doing;
cd /ApplicationRoot/Angular-App;
ng serve --verbose --progress --host 0.0.0.0 --port 80 --poll 1;'
volumes:
ApplicationRootVolume:
external:
name: Angular-in-Docker-by-Windows-share-folder
AngularAppNodeModules:
Docker-Compose-Startup-Order:
下面详细讲解docker-compose.yaml
文件。
Version
版本此处使用docker-compose
文件的3.4
版本,
如果docker-compose
不支持这么高的版本可能不能正常运行。
version: "3.4"
Volume
卷volumes:
ApplicationRootVolume:
external:
name: Angular-in-Docker-by-Windows-share-folder
AngularAppNodeModules:
Docker-Compose-Startup-Order:
其中共包含三个卷。
ApplicationRootVolume
为前面使用脚本共享的Windows
文件夹AngularAppNodeModules
为内部卷,用于node_modules
文件夹, node
安装的模块都放在docker
中, Visual Studio Code
打开的时候,找不到这些模块,没有代码提示。Docker-Compose-Startup-Order
为内部卷, docker-compose
中服务的启动顺序。node-npm-9.10.0-5.8.0
node-npm-9.10.0-5.8.0:
image: node-npm:9.10.0-5.8.0
build:
context: .
dockerfile: node-npm-9.10.0-5.8.0.Dockerfile
这个服务的目的就是用于构建node-npm:9.10.0-5.8.0
镜像,
构建文件为node-npm-9.10.0-5.8.0.Dockerfile
,代码如下
FROM node:9.10.0
LABEL maintainer="[email protected]"
RUN node --version && \
npm version && \
npm -g install npm@5.8.0 && \
npm version
很简单,从node:9.10.0
升级[email protected]
,
这里精确标注版本为了避免经常出现的版本冲突,如果后续遇到版本冲突,
建议按照类似的格式精确构建版本。
本服务的构建过程仅需要运行一次,再次运行不会重复构建镜像。
angular.cli-1.7.3
angular.cli-1.7.3:
depends_on:
- node-npm-9.10.0-5.8.0
image: angular.cli:1.7.3
build:
context: .
dockerfile: angular.cli-1.7.3.Dockerfile
这个服务的目的也是用于构建镜像,镜像为angular.cli:1.7.3
,
构建文件为angular.cli-1.7.3.Dockerfile
,代码如下
FROM node-npm:9.10.0-5.8.0
LABEL maintainer="[email protected]"
RUN npm install -g --unsafe-perm=true @angular/cli@1.7.3 && \
ng version
注意这里使用服务node-npm-9.10.0-5.8.0
构建的node-npm:9.10.0-5.8.0
镜像,
为了控制构建顺序,需要设置依赖关系。
depends_on:
- node-npm-9.10.0-5.8.0
构建内容就是安装@angular/[email protected]
,然后显示版本ng version
。
本服务的构建过程仅需要运行一次,再次运行不会重复构建镜像。
由于构建镜像不稳定,建议在构建镜像后保存镜像,因为都是开源软件,
所以可以保存在docker
的公共镜像库中,在 http://hub.docker.com/ 上注册账号。
在本地登录
docker login
在 http://hub.docker.com/ 上创建镜像仓库,我创建的镜像仓库为
在本地按照镜像仓库的名称给镜像打标签。
docker tag node-npm:9.10.0-5.8.0 huzhenghui/node-npm:9.10.0-5.8.0
docker tag angular.cli:1.7.3 huzhenghui/angular.cli:1.7.3
然后上传镜像。
docker push huzhenghui/node-npm:9.10.0-5.8.0
docker push huzhenghui/angular.cli:1.7.3
上传后即可在 http://hub.docker.com/ 上看到。
https://hub.docker.com/r/huzhenghui/node-npm/
https://hub.docker.com/r/huzhenghui/angular.cli/
未来使用的时候,可以拉取镜像,拉取镜像不需要登录。
docker pull huzhenghui/node-npm:9.10.0-5.8.0
docker pull huzhenghui/angular.cli:1.7.3
然后测试镜像
docker run -it --rm huzhenghui/angular.cli:1.7.3 ng -v
docker run -it --rm huzhenghui/angular.cli:1.7.3 bash
为了和docker-compose.yml
中的镜像名称保持一致,给镜像打标签。
docker tag huzhenghui/node-npm:9.10.0-5.8.0 node-npm:9.10.0-5.8.0
docker tag huzhenghui/angular.cli:1.7.3 angular.cli:1.7.3
ng-new
ng-new:
depends_on:
- angular.cli-1.7.3
image: angular.cli:1.7.3
volumes:
- type: volume
source: ApplicationRootVolume
target: /ApplicationRoot
- type: volume
source: AngularAppNodeModules
target: /ApplicationRoot/Angular-App/node_modules
- Docker-Compose-Startup-Order:/Startup-Order
command: |
bash -c '
echo ng-new start;
touch /Startup-Order/ng-new.start;
cd /ApplicationRoot;
ng new Angular-App;
echo ng-new done return code = $$?;
touch /Startup-Order/ng-new.done;'
这个服务用于新建angular
项目,使用前面构建的angular.cli:1.7.3
,
因此设置依赖关系。
depends_on:
- angular.cli-1.7.3
挂载了三个卷,其中
ApplicationRootVolume
是从Windows
共享的文件夹,挂载在/ApplicationRoot
AngularAppNodeModules
是内部卷, /ApplicationRoot/Angular-App/node_modules
。 ApplicationRootVolume
挂载位置的内部, docker
的强大功能之一,可以灵活的控制文件写入的位置。Docker-Compose-Startup-Order
是内部卷,挂载在/Startup-Order
服务的命令直接写脚本,头尾用于控制服务的运行顺序。
touch /Startup-Order/ng-new.start;
touch /Startup-Order/ng-new.done;
中间部分这是新建angular
项目。
cd /ApplicationRoot;
ng new Angular-App;
仅在首次运行的时候有较长的运行时间,
再次运行的时候检测到已经创建了项目就会自动结束。
npm-install
npm-install:
depends_on:
- ng-new
image: angular.cli:1.7.3
volumes:
- type: volume
source: ApplicationRootVolume
target: /ApplicationRoot
- type: volume
source: AngularAppNodeModules
target: /ApplicationRoot/Angular-App/node_modules
- Docker-Compose-Startup-Order:/Startup-Order
command: |
bash -c '
echo npm-install start;
touch /Startup-Order/npm-install.start;
while [[ ! -f /Startup-Order/ng-new.done || /Startup-Order/ng-new.done -ot /Startup-Order/ng-new.start ]]; do sleep 1; done;
echo npm-install doing;
cd /ApplicationRoot/Angular-App;
npm install;
echo npm-install done;
touch /Startup-Order/npm-install.done;'
代码结构和服务ng-new
类似,命令的头尾也是用于控制服务的运行顺序。
touch /Startup-Order/npm-install.start;
while [[ ! -f /Startup-Order/ng-new.done || /Startup-Order/ng-new.done -ot /Startup-Order/ng-new.start ]]; do sleep 1; done;
touch /Startup-Order/npm-install.done;'
其中的while
循环就是检测服务ng-new
是否运行结束,对照服务ng-new
即可理解。
中间部分是安装node
包。
cd /ApplicationRoot/Angular-App;
npm install;
仅在首次运行的时候有较长的运行时间,
再次运行的时候检测到已经安装了包就会自动结束。
ng-serve
ng-serve:
depends_on:
- npm-install
image: angular.cli:1.7.3
volumes:
- type: volume
source: ApplicationRootVolume
target: /ApplicationRoot
- type: volume
source: AngularAppNodeModules
target: /ApplicationRoot/Angular-App/node_modules
- Docker-Compose-Startup-Order:/Startup-Order
ports:
- 80:80
command: |
bash -c '
echo ng-serve start;
while [[ ! -f /Startup-Order/npm-install.done || /Startup-Order/npm-install.done -ot /Startup-Order/npm-install.start ]]; do sleep 1; done;
echo ng-serve doing;
cd /ApplicationRoot/Angular-App;
ng serve --verbose --progress --host 0.0.0.0 --port 80 --poll 1;'
代码结构和服务ng-new
类似,
区别在于服务ng-serve
提供web
服务,因此需要打开80
端口。
ports:
- 80:80
命令头部的while
循环就是检测服务npm-install
是否运行结束,
对照服务npm-install
即可理解。
while [[ ! -f /Startup-Order/npm-install.done || /Startup-Order/npm-install.done -ot /Startup-Order/npm-install.start ]]; do sleep 1; done;
然后启动web
服务。
ng serve --verbose --progress --host 0.0.0.0 --port 80 --poll 1;
其中--host 0.0.0.0
为绑定全部地址,默认仅绑定localhost
,
在docker
中运行时外部是访问不到的。
--port 80
为绑定80
端口,默认绑定4200
端口。
--poll 1
用于加快检查文件是否有更新,后面Visual Studio Code
环节会详细讲解。
4
步:打开浏览器因为第一个PowerShell
窗口中正在显示ng-serve
服务,
因此需要运行另一个PowerShell
窗口,进入到代码文件夹。
.\step.4.open.browser.ps1
代码如下。
if ($env:DOCKER_HOST -match "\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b")
{
Start-Process (-Join('http://', $Matches[0], '/'))
}
其中$env:DOCKER_HOST
是docker
的环境变量,使用如下代码查看。
Write-Output $env:DOCKER_HOST
输出结果类似为
tcp://192.168.1.101:2376
脚本从这个环境变量中解析出IP
地址,本例中即为192.168.1.101
,
然后拼接成网址,本例中即为http://192.168.1.101/
,
再打开浏览器访问,Windows
下默认为Edge
浏览器。
打开浏览器后应能看到angular
项目的初始界面,
如果看不到请按照按照前面的讲解排查。
5
步:使用Visual Studio Code
打开Angular
应用文件夹继续在第二个PowerShell
窗口中运行。
.\step.5.open.code.ps1
内容如下。
if ($env:DOCKER_HOST -match "\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b")
{
if(!(Test-Path .\Angular-App\.vscode))
{
New-Item -ItemType "directory" .\Angular-App\.vscode\
}
if(!(Test-Path .\Angular-App\.vscode\launch.json))
{
$launch=Get-Content -Encoding UTF8 .\Angular-App.vscode.launch.json | ConvertFrom-Json
$launch.configurations[0].name=-Join("Launch Chrome and Open ", $Matches[0])
$launch.configurations[0].url=-Join('http://', $Matches[0], '/')
$launch | ConvertTo-Json | Out-File -Encoding UTF8 .\Angular-App\.vscode\launch.json
}
}
code .\Angular-App\
脚本的第一部分是自动配置Chrome
调试,和前面类似,也是先解析出IP
地址。
如果没有.\Angular-App\.vscode
文件夹则创建该文件夹。
如果没有.\Angular-App\.vscode\launch.json
则从模板创建。创建方式简单粗暴,
直接使用默认生成的launch.json
文件创建,
因此如果遇到Visual Studio Code
版本升级导致不兼容,
请参照这里介绍的工作原理调试。
读取模板后,修改name
名称,和url
地址,然后保存到目标位置。
脚本的第二部分自动启动Visual Studio Code
,当然需要电脑上安装Visual Studio Code
。
等Visual Studio Code
启动后可以测试自动更新。
Visual Studio Code
将自动打开Chrome
浏览器(需要电脑上安装Chrome
浏览器)Chrome
浏览器是否自动访问页面src/app/app.component.ts
中的标题名称PowerShell
窗口是否自动更新Chrome
浏览器是否自动刷新6
步:停止继续在第二个PowerShell
窗口中运行。
.\step.6.docker-compose.down.ps1
代码很简单。
docker-compose down
观察第一个PowerShell
窗口是否停止服务。
需要注意停止服务时需要在启动服务相同的文件夹。
7
步:清理不再使用的时候,可以运行清理脚本
.\step.7.clean.ps1
代码如下。
Remove-Item -Recurse -Force .\Angular-App\* -Confirm
Remove-Item .\Angular-App\
docker volume rm angularindockerbywindowssharefolder_AngularAppNodeModules
docker volume rm angularindockerbywindowssharefolder_Docker-Compose-Startup-Order
删除新建的angular
项目,删除docker
中相关的卷。