2019年6月20日 星期四

Azure Devops Server 2019 更改電腦名稱

Azure Devops Server 2019 更改電腦名稱

在新VM裡安裝 Azure Devops Server 2019 時,沒有注意電腦名稱是什麼,後來想要改電腦名稱時,也沒想那麼多就直接改了。結果,改完重開機就連不上web 介面了,一直轉圈圈。
心裡想一定有什麼跟電腦名稱綁在一起無法執行。 後來在

C:\Program Files\Azure DevOps Server 2019\Application Tier\Web Services\web.config

找到資料庫連線字串的設定是用電腦名稱

    <add key="applicationDatabase" value="Data Source=WIN-IL123HEV1A2;Initial Catalog=AzureDevOps_Configuration;Integrated Security=True;Encrypt=False" />

把 Data Source 換成新的電腦名稱再重新開機一次就都正常了。

2019年6月18日 星期二

Azure Pipelines 建立部署群組卡關

Azure Pipelines 建立部署群組卡關

現在在測試新的Devpos環境, 以現有使用TFS的經驗,Azure Devops Server 2019 自然是第一個考慮的工具。

把Azure Devops Server 2019 的安裝比較沒什麼問題,基本上安裝程式會檢查環境,有缺什麼會顯示出來。例如:要先安裝SQL SERVER;要有JDK(沒有的話,打個勾勾會自動裝OpenJDK) 。 這個比遙遠的當年 TFS 2005 裝了好幾天才裝起來好太多了 。

不過安裝好之後,要在pipelines建第一個部署群組就卡關了,"部署群組"就是要部署到哪裡去,被部署的SERVER上面要裝一個代理程式( agent) 。

But… 安裝agent,居然是叫你自己下powershell command的方式。虧我前面還在誇Azure Devops Server 2019的安裝介面做的不錯。

雖然在介面上他己經產生好script,把他貼到powershell裡面去執行就好了。看起來一塊蛋榚啊!! 介面長的像這樣
部署群組圖1

照畫面上的指示,把那一堆Script放到powershell的command裡執行
結果
部署群組圖二

哇哩,反覆的仔細檢查script.

才發現179字元 “Administrator” 有問題, 把 “ ” 換成正常的 "

enter image description here

再來一次

PS C:\> $ErrorActionPreference="Stop";If(-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent() ).IsInRole( [Security.Principal.WindowsBuiltInRole] "Administrator")){ throw "在系統管理員 PowerShell 提示字元處執行命令"};If($PSVersionTable.PSVersion -lt (New-Object System.Version("3.0"))){ throw "指令碼 (3.0) 需要的 Windows PowerShell 最低版本,與目前正在執行的 Windows PowerShell 版本不符。" };If(-NOT (Test-Path $env:SystemDrive\'azagent')){mkdir $env:SystemDrive\'azagent'}; cd $env:SystemDrive\'azagent'; for($i=1; $i -lt 100; $i++){$destFolder="A"+$i.ToString();if(-NOT (Test-Path ($destFolder))){mkdir $destFolder;cd $destFolder;break;}}; $agentZip="$PWD\agent.zip";$DefaultProxy=[System.Net.WebRequest]::DefaultWebProxy;$securityProtocol=@();$securityProtocol+=[Net.ServicePointManager]::SecurityProtocol;$securityProtocol+=[Net.SecurityProtocolType]::Tls12;[Net.ServicePointManager]::SecurityProtocol=$securityProtocol;$WebClient=New-Object Net.WebClient; $Uri='https://go.microsoft.com/fwlink/?linkid=2066756';if($DefaultProxy -and (-not $DefaultProxy.IsBypassed($Uri))){$WebClient.Proxy= New-Object Net.WebProxy($DefaultProxy.GetProxy($Uri).OriginalString, $True);}; $WebClient.DownloadFile($Uri, $agentZip);Add-Type -AssemblyName System.IO.Compression.FileSystem;[System.IO.Compression.ZipFile]::ExtractToDirectory( $agentZip, "$PWD");.\config.cmd --deploymentgroup --deploymentgroupname "first" --agent $env:COMPUTERNAME --runasservice --work '_work' --url 'http://172.16.1.111/' --collectionname 'DefaultCollection' --projectname 'uuuu' --auth Integrated; Remove-Item $agentZip;


    目錄: C:\azagent


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----        2019/6/17  下午 03:18                A1


>> 連線:

正在連線到伺服器...

>> 註冊代理程式:

正在掃描工具功能。
正在連接至伺服器。
請輸入 代理程式的部署群組標記? (Y/N) (請為 否 按 Enter) >
已成功新增代理程式
正在測試代理程式連線。
2019-06-17 07:22:07Z: 已儲存設定。
請輸入 要用於服務的使用者帳戶 (請為 NT AUTHORITY\SYSTEM 按 Enter) >
正在將檔案權限授與 'NT AUTHORITY\SYSTEM'。
已成功安裝服務 vstsagent.172.TEST
服務 vstsagent.172.TEST 已成功設定復原選項
服務 vstsagent.172.TEST 已成功設定為延遲自動啟動
已成功設定服務 vstsagent.172.TEST
已成功啟動服務 vstsagent.172.TEST

終於可以註冊上去了,握拳!!


同場加映:如何移除 agent

從上面的script可以發現,他其實只做2件事,

  1. 下載1個zip 檔,然後解壓縮到C:\azagent\A1
  2. 執行裡面的config.cmd 跟著一堆參數

所以要移除agent , 一樣用有管理員身分的powershell到C:\azagent\A1 裡執行 config.cmd 只是參數換成remove

PS C:\azagent\a1> .\config.cmd remove
正在移除服務
正在等候服務結束...
成功:正在移除服務
正在從伺服器移除代理程式
請輸入 驗證類型 (請為 Integrated 按 Enter) >
正在連線到伺服器...
成功:正在從伺服器移除代理程式
正在移除 .credentials
成功:正在移除 .credentials
正在移除 .agent
成功:正在移除 .agent

2019年6月14日 星期五

docker compose 在重開機之後無法啟動

docker compose 在重開機之後無法啟動.md

今天在試時 docker compose 發現host 重開機之後,下指令啟動,但卻無法啟動。

C:\web>docker-compose.exe start
Starting proxy      ... error
Starting site1      ... error
Starting site2      ... error

ERROR: for proxy  Cannot start service proxy: network 02fda54dd66e8782205ee417e901b198279abd40f74b2ffd970fcabc336db8eb not found
ERROR: No containers to start

看起來是找不到network。 真是見鬼了,用network ls 一看,真的不見了。

C:\web>docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
202191da323c        nat                 nat                 local
6f2b7ad221fe        none                null                local

後來才想起來 windows server 2019 重開機之後不會保留 driver 為 nat 的 network。
另一個悲傷的故事

既然 start 的指令無法啟動,那 up 指令會怎樣呢?

C:\web>docker-compose.exe up -d
Creating network "web_lan" with driver "nat"
Starting proxy ... error

ERROR: for proxy  Cannot start service proxy: network 02fda54dd66e8782205ee417e901b198279abd40f74b2ffd970fcabc336db8eb not found

ERROR: Encountered errors while bringing up the project.

看到第一行輸出時,心裡還 “耶” 了一下,結果第二行就…

這個也很奇怪,明明network建起來了,但是找不到??? 一整個黑人問號
用network ls看,還真的有建起來

C:\web>docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
88d33743ebc0        web_lan             nat                 local
202191da323c        nat                 nat                 local
6f2b7ad221fe        none                null                local

仔細一看network id ,原來不一樣了。 哇哩!! 新建的network id不一樣, 但是docker不會自動使用新的但是同名的network!!!

那…全部刪掉再建總可以了吧!!

docker-compose down
docker-compose up -d

總算建起來了。
但是只能這樣解嗎? 底下是我的 docker-compose.yml

version: '3.7'

services:
 proxy:
  image : proxy
  container_name: proxy
  restart: always
  networks:
   lan: 
  ports:
   - "80:80"

 site1:
  image : web
  container_name: site1
  ports:
   - "8000:80"
  networks:
   lan:
  depends_on:
   - "proxy"
  restart: always
 site2:
  image : web
  container_name: site2
  ports:
   - "8001:80"
  networks:
   lan:
  depends_on:
   - "proxy"
  restart: always 
networks:
 lan:
  driver: nat

lan 這個network是跟著docker compose一起建起來的。 那不要一起建,先在外面建好總可以吧!!
底下是修改過的 docker-compose.yml

version: '3.7'

services:
 proxy:
  image : proxy
  container_name: proxy
  restart: always
  networks:
   lan: 
  ports:
   - "80:80"

 site1:
  image : web
  container_name: site1
  ports:
   - "8000:80"
  networks:
   lan:
  depends_on:
   - "proxy"
  restart: always
 site2:
  image : web
  container_name: site2
  ports:
   - "8001:80"
  networks:
   lan:
  depends_on:
   - "proxy"
  restart: always 
networks: 
 lan: 
  external: 
   name: nat

建立一個network 叫lan,連結到外部現有的network叫 “nat” 。

#新建時就不會建立新的network
C:\web>docker-compose up -d
Creating proxy      ... done
Creating site1      ... done
Creating site2      ... done

#移除時,docker會發現是外部的network然後就略過
C:\web>docker-compose down
Removing site2      ... done
Removing site1      ... done
Removing proxy      ... done
Network nat is external, skipping

在windows server 2019上使用 docker 建立 driver 為 nat 的 network 重開機之後會消失

在windows server 2019上使用 docker 建立 driver 為 nat 的 network 重開機之後會消失

一開始我以為我發現了一個 windows server 2019 (1809) 的BUG 。

docker create network -d nat mynet

用上面的指令 在docker create network driver 用 nat 的話 ,重開機後,mynet就不見惹。

2018/12 月在 github 就有人 report 這個issue , 但是一直沒修。 https://github.com/docker/for-win/issues/3076

再深入追查才發現這是微軟預設的行為… 我的老天鵝啊!!! 這不合理吧!!!

NAT networks created on Windows Server 2019 (or above) are no longer persisted after reboot.

https://docs.microsoft.com/en-us/virtualization/windowscontainers/container-networking/network-drivers-topologies

並沒有解釋為什麼~~~ 啊啊啊!!! (請允許我內心的哀嚎) 這樣的預設設定不是自癈武功嗎??

山不轉路轉

每次重開機重建network 總行了吧!!

用下面的powershell script 用工作排程器在開機時執行

$networkName = "mylan"
$ErrorActionPreference = "silentlycontinue"
$inspectResult = & docker network inspect $networkName
$ErrorActionPreference = "continue"
#如果network 不存在就建一個新的
if($LASTEXITCODE -eq 1) {
  docker network create -d nat --subnet 192.168.1.0/24 -o com.docker.network.windowsshim.networkname=Docker-$networkName $networkName
} 

哀嚎加演場

後來測試,建立新的network 然後 driver 用 transparent

docker create network -d transparent mynet

一樣會不見!! 我本來己經準備在臉上寫一個慘字了。

還好做完 windows update , network driver 是 transparent 就不會在重開機之後不見了。 應該是 KB4497934KB4494441 其中之一修好的。
windows update for server 2019

但是我在KB的更新說明裡面找不到相關的說明,算了,反正有修就好。

docker for windows 的 volume 無法掛載網路磁碟機

docker for windows 的 volume 無法掛載網路磁碟機

在windows container怎樣把網路磁碟機掛成 Volume, 試了很久。 包括 net use 成一個碟碟機之後再試了就是掛不進去。
google 很久找到的 solution 都是 for linux 的. 在 windows 上要把網路上的磁碟機掛成 volume 似乎就只有類似像 iSCSI 這種方式而己。

山不轉路轉

後來突然轉念, 直接在 container 裡掛起來就好了啊

在container裡下

net use z: "\\172.16.0.10\folder" /user:eric mypassword

還可以再把網路磁碟機變成C槽的某個資料夾

mklink /d z:\ c:\files

2019年6月10日 星期一

WordPress的效能改善

WordPress的效能改善

先說結論

  1. 把PHP的版本升到最新版

  2. 修改 wp-config.php
    把原本

/** MySQL hostname */  
define( 'DB_HOST', 'localhost' );

改成

/** MySQL hostname */  
define( 'DB_HOST', '127.0.0.1' );
  1. 使用page cache 的 plugin 。(我是用 Cache Enabler ,應該是還有其他的選擇)

故事是這樣的

最近要把官網改版,然後使用wordpress來製作,這樣可以讓不懂程式的相關人員可以自己更動網站內容。

BUT ,代誌不是憨人想的那麼簡單

網站快上線時才發現,天啊!! 怎麼這麼慢。 Waiting TTFB (Time To First Byte) 居然要超過4秒。整個網頁跑完十多秒過去了。

於是開始神農嘗百草的日子,先是找到把PHP 從 5.6 升到 7.3 可以縮短約 2000 ms 。 把我們使用的 wordpress 樣版升到最新版本,也有快一點點縮短約500ms 。

現在 TTFB 來到約 2500 ms,還是太慢了。 再來試過很多方法,例如,開啟PHP的opcache , 加大PHP的可用記憶體(memory_limit) 都沒什麼作用。

弄很久才終於找到,把wp-config.php 裡mysql的位址從 localhost 改成 127.0.0.1 馬上縮短1000個ms。 為什麼有效的原因是,因為改成用 IP 之後 ,不需要作內部的 DNS 解析。

再加上wordpress 的 cache plugin,我是用 Cache Enabler 可以讓同一個page 的第二次 request 縮短約 1000ms。

現在首頁在有cache 的狀況下,TTFB大約在20-70ms。算還可以,網站就先這樣上線了。

2019年6月4日 星期二

在IIS 上 CSS,圖片,JS 這幾種類型的檔案, 突然出現 500 INTERNAL SERVER ERROR

在IIS 上 CSS,圖片,JS 這幾種類型的檔案, 突然出現 500 INTERNAL SERVER ERROR

今天在主要對外的網站收到想要讓使用者下載 apk 檔的需求,我想說一塊蛋榚,找一下apk 的MIME Type

application/vnd.android.package-archive

就直接把這個設定加到IIS上電腦層級的MIME Type 設定,然後就去忙別的事了。

沒多久就有人開始反應,全部網站的STYLE全跑掉了。 用開發者工具一看,天啊!! 所有的CSS , 圖片,跟javascript 檔全都回應狀態500。

一開始重啟IIS…沒效,重開機…沒效。 後來突然想到是不是我動了設定的關係,就把剛剛加的MIMETYPE 刪掉… 就好了!!

問一下Google 大神原來還不少人有遇過一樣的症頭。
解法就是改成在 web.config設定, 加入MIMETYPE前,先移掉該type。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <staticContent>
            <remove fileExtension=".apk" />
            <mimeMap fileExtension=".apk" mimeType="application/vnd.android.package-archive" />
        </staticContent>
    </system.webServer>
</configuration>