<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>container 彙整 - 泰克哪裡去</title>
	<atom:link href="https://tech.uccu.website/tag/container/feed" rel="self" type="application/rss+xml" />
	<link>https://tech.uccu.website/tag/container</link>
	<description>一個科技相關的隨手記錄網站</description>
	<lastBuildDate>Sun, 09 Oct 2022 14:59:11 +0000</lastBuildDate>
	<language>zh-TW</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8.1</generator>
<site xmlns="com-wordpress:feed-additions:1">119574712</site>	<item>
		<title>【2022鐵人賽】使用Task與CLI的抉擇</title>
		<link>https://tech.uccu.website/2022ironman-day22-task-or-cli.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=2022ironman-day22-task-or-cli</link>
					<comments>https://tech.uccu.website/2022ironman-day22-task-or-cli.html#respond</comments>
		
		<dc:creator><![CDATA[鳴人]]></dc:creator>
		<pubDate>Sat, 08 Oct 2022 14:37:38 +0000</pubDate>
				<category><![CDATA[2022鐵人賽]]></category>
		<category><![CDATA[Azure DevOps]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[iThome鐵人賽]]></category>
		<category><![CDATA[2022ironman]]></category>
		<category><![CDATA[azure devops]]></category>
		<category><![CDATA[container]]></category>
		<category><![CDATA[linux]]></category>
		<guid isPermaLink="false">https://tech.uccu.website/?p=2055</guid>

					<description><![CDATA[<p>透過CLI就是組Scripts來達成目的，所以彈性相對高很多。除了可以Build Source Code之外，要Pack Nuget Package也是同樣透過Sdk CLI就可以達成。但是如果是用Task的話，可能就會需要分成不同的Task。</p>
<p>這篇文章 <a href="https://tech.uccu.website/2022ironman-day22-task-or-cli.html">【2022鐵人賽】使用Task與CLI的抉擇</a> 最早出現於 <a href="https://tech.uccu.website">泰克哪裡去</a>。</p>
]]></description>
										<content:encoded><![CDATA[
<p>這篇要來聊聊Azure DevOps Pipeline的Task與CLI的抉擇，為什麼會這樣說呢？</p>



<p>因為其實在Azure DevOps Pipeline中已經有提供許多不錯的Task設計，尤其.Net的程式在Azure DevOps Pipeline中有各式各樣對應的Task可以使用，像去年的文章「<a href="https://tech.uccu.website/2021ironman-day7-first-pipeline-template-and-editor.html">CI/CD從這裡：設定第一個Pipeline(範本與編輯介面介紹)</a>」裡面就是使用內建的VSBuild Task來編譯.Net的程式碼，但是今年卻在「<a href="https://tech.uccu.website/2022ironman-day8-ci-pipeline-buildcode.html" target="_blank" rel="noreferrer noopener">基本版-建立CI Pipeline(1)</a>」文章內一開始就使用.Net Sdk的Container來編譯.Net的程式碼…</p>



<p>除了今年的文章屬於進階應用之外，還有其它幾個不同的因素考量：</p>



<ul class="wp-block-list"><li>Task要透過GUI才能快速方便知道有什麼參數可以選擇與設定</li><li>不同功能可能要選用不同task</li><li>可以達到相同功能的Task可能不只一個</li><li>想要測試看看執行結果如何無法在Pipeline以外的環境執行</li><li>用Container或直接用Sdk CLI可以在本機執行看看結果</li><li>新功能或指令在Task可能沒有設計或支援</li><li>如果是自管的Agent只要裝了Docker就可以</li></ul>



<p>因為透過CLI就是組Scripts來達成目的，所以彈性相對高很多。例如.Net Core Sdk CLI除了可以Build Source Code之外，要Pack Nuget Package也是同樣透過Sdk CLI就可以達成，只是指令的組成不太一樣。但是如果是用Task的話，就會需要分成Nuget Task與.Net Core Task，或是pack也用.Net Core Task而不是用Nuget Task。</p>



<p>另外還有像是我們使用Azure DevOps Artifacts功能來存放私有的Nuget Packages，不過要Push上去是需要身份驗證授權的，在Task的選擇部份就有Nuget authenticate Task(搭配設定Service Connection)，或是有個nuget.config檔案，裡面寫入PAT然後放在特定的位置來自動解決身份驗證的問題。</p>



<p>所以原本的dotnet-build-in-linux-container.yaml就可以重新做一份step template：</p>



<pre class="wp-block-prismatic-blocks"><code class="language-yaml"># steps/dotnet-sdk-in-linux-container.yaml

parameters:
  - name: dotnetSdkImgRepository
    type: string
    default: mcr.microsoft.com/dotnet/sdk:6.0-alpine
  - name: srcPath
    type: string
  - name: outputPath
    type: string
    default: $(Build.ArtifactStagingDirectory)/outputFiles/
  - name: slnOrCsprojName
    type: string
    default: Pipeline.sln
  - name: dotnetCommand
    type: string
  - name: dotnetCommandArgs
    type: string

steps:
  - script: |    
      echo &quot;Dotnet sdk in linux container template&quot;
      echo &quot;${{ convertToJson(parameters) }}&quot;
    displayName: Print template parameters
  - task: Bash@3
    displayName: Run dotnet sdk command in container
    inputs:
      targetType: &#039;inline&#039;
      script: |
        if [ -d ${{ parameters.outputPath }} ]; then echo &quot;${{ parameters.outputPath }} exist&quot;; else mkdir -p ${{ parameters.outputPath }}; fi
        export UID=$(id -u)
        export GID=$(id -g)
        docker run --user $UID:$GID --rm \
        -v ${{ parameters.srcPath }}:/tmp/source \
        -v ${{ parameters.outputPath }}:/tmp/publish \
        -e DOTNET_CLI_HOME=/tmp/.dotnet \
        ${{ parameters.dotnetSdkImgRepository }} \
        dotnet ${{ parameters.dotnetCommand }} /tmp/source/${{ parameters.slnOrCsprojName }} \
        -o /tmp/publish ${{ parameters.dotnetCommandArgs }} \
  - task: ArchiveFiles@2
    displayName: 壓縮成zip
    inputs:
      rootFolderOrFile: $(Build.BinariesDirectory)
      includeRootFolder: false
      archiveType: &#039;zip&#039;
      archiveFile: &#039;$(Build.ArtifactStagingDirectory)/zipFiles/buildResult.zip&#039;
      replaceExistingArchive: true</code></pre>



<p>這樣就可以用同樣的一個範本搞定Build Source Code、Pack Nuget Package之類的事情，對應在jobs/buildCode.yaml就是把引用的template檔案改成新的，然後加上dotnetCommand、dotnetCommandArgs參數的設定就行了。</p>



<pre class="wp-block-prismatic-blocks"><code class="language-yaml">      - template: ../steps/dotnet-sdk-in-linux-container.yaml
        parameters:
          srcPath: ${{ parameters.sourcePath }}
          slnOrCsprojName: ${{ parameters.slnOrCsprojName }}
          dotnetCommand: publish
          dotnetCommandArgs: &#039;-c ${{ parameters.buildConfiguration }}&#039;</code></pre>
<p>這篇文章 <a href="https://tech.uccu.website/2022ironman-day22-task-or-cli.html">【2022鐵人賽】使用Task與CLI的抉擇</a> 最早出現於 <a href="https://tech.uccu.website">泰克哪裡去</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tech.uccu.website/2022ironman-day22-task-or-cli.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2055</post-id>	</item>
		<item>
		<title>【2021鐵人賽】建立自管的Azure DevOps Agent(Linux Container agent)</title>
		<link>https://tech.uccu.website/2021ironman-day22-build-linux-container-image-for-azure-devops-agent.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=2021ironman-day22-build-linux-container-image-for-azure-devops-agent</link>
					<comments>https://tech.uccu.website/2021ironman-day22-build-linux-container-image-for-azure-devops-agent.html#respond</comments>
		
		<dc:creator><![CDATA[鳴人]]></dc:creator>
		<pubDate>Mon, 04 Oct 2021 15:40:42 +0000</pubDate>
				<category><![CDATA[2021鐵人賽]]></category>
		<category><![CDATA[Azure DevOps]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[iThome鐵人賽]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[資訊科技]]></category>
		<category><![CDATA[2021ironman]]></category>
		<category><![CDATA[azure devops]]></category>
		<category><![CDATA[container]]></category>
		<category><![CDATA[docker]]></category>
		<guid isPermaLink="false">https://tech.uccu.website/?p=1292</guid>

					<description><![CDATA[<p>前一篇文章建立了Azure DevOps Agent的Windows Container Image，已經知道了基本的概念就是：1.選擇基底映像檔、2.安裝所需要的額外套件與程式、3.將Azure DevOps Agent的開始程式start.ps/start.sh複製進去。</p>
<p>這篇文章 <a href="https://tech.uccu.website/2021ironman-day22-build-linux-container-image-for-azure-devops-agent.html">【2021鐵人賽】建立自管的Azure DevOps Agent(Linux Container agent)</a> 最早出現於 <a href="https://tech.uccu.website">泰克哪裡去</a>。</p>
]]></description>
										<content:encoded><![CDATA[
<p><a href="https://tech.uccu.website/2021ironman-day21-build-windows-container-image-for-azure-devops-agent.html" target="_blank" rel="noreferrer noopener">前一篇文章</a>建立了Azure DevOps Agent的Windows Container Image，已經知道了基本的概念就是：</p>



<ol class="wp-block-list"><li>選擇基底映像檔</li><li>安裝所需要的額外套件與程式</li><li>將Azure DevOps Agent的開始程式start.ps/start.sh複製進去</li></ol>



<p>既然已經知道了上面的概念，前一篇也有做過一次，那麼這篇就少浪費一些篇幅，直接把Code端上來看吧！</p>



<p>start.sh的內容如下，記得要改成Unix格式的結束符號(LF)喔！(或是透過dos2unix轉換)</p>



<pre class="wp-block-prismatic-blocks"><code class="language-bash">#!/bin/bash
set -e

if [ -z &quot;$AZP_URL&quot; ]; then
  echo 1&gt;&amp;2 &quot;error: missing AZP_URL environment variable&quot;
  exit 1
fi

if [ -z &quot;$AZP_TOKEN_FILE&quot; ]; then
  if [ -z &quot;$AZP_TOKEN&quot; ]; then
    echo 1&gt;&amp;2 &quot;error: missing AZP_TOKEN environment variable&quot;
    exit 1
  fi

  AZP_TOKEN_FILE=/azp/.token
  echo -n $AZP_TOKEN &gt; &quot;$AZP_TOKEN_FILE&quot;
fi

unset AZP_TOKEN

if [ -n &quot;$AZP_WORK&quot; ]; then
  mkdir -p &quot;$AZP_WORK&quot;
fi

export AGENT_ALLOW_RUNASROOT=&quot;1&quot;

cleanup() {
  if [ -e config.sh ]; then
    print_header &quot;Cleanup. Removing Azure Pipelines agent...&quot;

    # If the agent has some running jobs, the configuration removal process will fail.
    # So, give it some time to finish the job.
    while true; do
      ./config.sh remove --unattended --auth PAT --token $(cat &quot;$AZP_TOKEN_FILE&quot;) &amp;&amp; break

      echo &quot;Retrying in 30 seconds...&quot;
      sleep 30
    done
  fi
}

print_header() {
  lightcyan=&#039;\033[1;36m&#039;
  nocolor=&#039;\033[0m&#039;
  echo -e &quot;${lightcyan}$1${nocolor}&quot;
}

# Let the agent ignore the token env variables
export VSO_AGENT_IGNORE=AZP_TOKEN,AZP_TOKEN_FILE

source ./env.sh

print_header &quot;1. Configuring Azure Pipelines agent...&quot;

./config.sh --unattended \
  --agent &quot;${AZP_AGENT_NAME:-$(hostname)}&quot; \
  --url &quot;$AZP_URL&quot; \
  --auth PAT \
  --token $(cat &quot;$AZP_TOKEN_FILE&quot;) \
  --pool &quot;${AZP_POOL:-Default}&quot; \
  --work &quot;${AZP_WORK:-_work}&quot; \
  --replace \
  --acceptTeeEula &amp; wait $!

print_header &quot;2. Running Azure Pipelines agent...&quot;

trap &#039;cleanup; exit 0&#039; EXIT
trap &#039;cleanup; exit 130&#039; INT
trap &#039;cleanup; exit 143&#039; TERM

# To be aware of TERM and INT signals call run.sh
# Running it with the --once flag at the end will shut down the agent after the build is executed
./run.sh &quot;$@&quot;</code></pre>



<p>官方的Dockerfile內容如下：</p>



<pre class="wp-block-prismatic-blocks"><code class="language-dockerfile">FROM ubuntu:18.04

# To make it easier for build and release pipelines to run apt-get,
# configure apt to not require confirmation (assume the -y argument by default)
ENV DEBIAN_FRONTEND=noninteractive
RUN echo &quot;APT::Get::Assume-Yes \&quot;true\&quot;;&quot; &gt; /etc/apt/apt.conf.d/90assumeyes

RUN apt-get update &amp;&amp; apt-get install -y --no-install-recommends \
    ca-certificates \
    curl \
    jq \
    git \
    iputils-ping \
    libcurl4 \
    libicu60 \
    libunwind8 \
    netcat \
    libssl1.0 \
  &amp;&amp; rm -rf /var/lib/apt/lists/*

RUN curl -LsS https://aka.ms/InstallAzureCLIDeb | bash \
  &amp;&amp; rm -rf /var/lib/apt/lists/*

ARG TARGETARCH=amd64
ARG AGENT_VERSION=2.185.1

WORKDIR /azp
RUN if [ &quot;$TARGETARCH&quot; = &quot;amd64&quot; ]; then \
      AZP_AGENTPACKAGE_URL=https://vstsagentpackage.azureedge.net/agent/${AGENT_VERSION}/vsts-agent-linux-x64-${AGENT_VERSION}.tar.gz; \
    else \
      AZP_AGENTPACKAGE_URL=https://vstsagentpackage.azureedge.net/agent/${AGENT_VERSION}/vsts-agent-linux-${TARGETARCH}-${AGENT_VERSION}.tar.gz; \
    fi; \
    curl -LsS &quot;$AZP_AGENTPACKAGE_URL&quot; | tar -xz

COPY ./start.sh .
RUN chmod +x start.sh

ENTRYPOINT [ &quot;./start.sh&quot; ]</code></pre>



<p>同樣的，上面的Dockerfile並不包含dotnet sdk，所以仍然需要自行安裝進去。</p>



<p>也和上一篇提到的一樣，我們可以透過在Docker hub上找到官方的dotnet sdk映像檔，找到我們要的OS版本，然後取代Dockerfile第一行的FROM後面使用的image repository：</p>



<figure class="wp-block-image size-large"><img data-recalc-dims="1" fetchpriority="high" decoding="async" width="1024" height="439" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/718841de-dotnetsdkimage-linuxamd64tags-1024x439.png?resize=1024%2C439&#038;ssl=1" alt="" class="wp-image-1298" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/718841de-dotnetsdkimage-linuxamd64tags.png?resize=1024%2C439&amp;ssl=1 1024w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/718841de-dotnetsdkimage-linuxamd64tags.png?resize=300%2C129&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/718841de-dotnetsdkimage-linuxamd64tags.png?resize=768%2C329&amp;ssl=1 768w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/718841de-dotnetsdkimage-linuxamd64tags.png?resize=1536%2C659&amp;ssl=1 1536w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/718841de-dotnetsdkimage-linuxamd64tags.png?w=1665&amp;ssl=1 1665w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>上圖的表格來自於微軟在<a href="https://hub.docker.com/_/microsoft-dotnet-sdk/" target="_blank" rel="noreferrer noopener">Docker Hub上的dotnet sdk頁面</a>，dotnet sdk的image repository是mcr.microsoft.com/dotnet/sdk:5.0，我們只需要將冒號後面的5.0改成需要的就行了，以上面紅框內容為例，就把5.0改為5.0-focal，這樣就是以Ubuntu 20.04為版本安裝了dotnet sdk 5.0製作的Docker image，再加上安裝PowerShell、Docker的話，最終的Dockerfile內容如下：</p>



<pre class="wp-block-prismatic-blocks"><code class="language-dockerfile">FROM mcr.microsoft.com/dotnet/sdk:5.0-focal

# To make it easier for build and release pipelines to run apt-get,
# configure apt to not require confirmation (assume the -y argument by default)
ENV DEBIAN_FRONTEND=noninteractive
RUN echo &quot;APT::Get::Assume-Yes \&quot;true\&quot;;&quot; &gt; /etc/apt/apt.conf.d/90assumeyes

#在這底下加入要額外裝在Docker Image內的程式

RUN apt-get update &amp;&amp; apt-get install -y --no-install-recommends \
    ca-certificates \
    curl \
    jq \
    git \
    iputils-ping \
    libcurl4 \
    libicu66 \
    libunwind8 \
    netcat \
    libssl1.0 \
	wget \
  &amp;&amp; rm -rf /var/lib/apt/lists/*

# 新增 Microsoft 存放庫金鑰和摘要
RUN wget https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb &amp;&amp; \
         dpkg -i packages-microsoft-prod.deb

# 安裝PowerShell
# Enable the &quot;universe&quot; repositories &amp; Install PowerShell
RUN apt-get update &amp;&amp; apt-get install -y powershell

# 安裝Docker
RUN apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
RUN curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add
RUN add-apt-repository \
   &quot;deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable&quot;
RUN apt-get update &amp;&amp; apt-get install docker-ce docker-ce-cli containerd.io

#===========================================

RUN curl -LsS https://aka.ms/InstallAzureCLIDeb | bash \
  &amp;&amp; rm -rf /var/lib/apt/lists/*

ARG TARGETARCH=amd64
ARG AGENT_VERSION=2.185.1

WORKDIR /azp
RUN if [ &quot;$TARGETARCH&quot; = &quot;amd64&quot; ]; then \
      AZP_AGENTPACKAGE_URL=https://vstsagentpackage.azureedge.net/agent/${AGENT_VERSION}/vsts-agent-linux-x64-${AGENT_VERSION}.tar.gz; \
    else \
      AZP_AGENTPACKAGE_URL=https://vstsagentpackage.azureedge.net/agent/${AGENT_VERSION}/vsts-agent-linux-${TARGETARCH}-${AGENT_VERSION}.tar.gz; \
    fi; \
    curl -LsS &quot;$AZP_AGENTPACKAGE_URL&quot; | tar -xz

COPY ./start.sh .
RUN chmod +x start.sh

ENTRYPOINT [ &quot;./start.sh&quot; ]</code></pre>



<p>上面的Dockerfile內容中要特別提一下在官方的範例中安裝的libicu60 package只適用在Ubuntu 18.04(<a href="https://askubuntu.com/questions/1225781/unable-to-locate-package-libicu60" target="_blank" rel="noreferrer noopener">參考這篇</a>)，因為我是選Ubuntu 20.04，所以改成libicu66(<a href="https://github.com/dotnet/core/issues/4360#issuecomment-618638299" target="_blank" rel="noreferrer noopener">參考這篇</a>)。</p>



<p>準備好Dockerfile和start.sh這兩個檔案之後，執行下面的指令建立映像檔：</p>



<pre class="wp-block-prismatic-blocks"><code class="language-docker">docker build -t devopsagent .</code></pre>



<p>完成Build Image的動作之後，透過下面的指令建立一個名為azure-agent的Container：</p>



<pre class="wp-block-prismatic-blocks"><code class="language-docker">docker run --name azure-agent -d -v /var/run/docker.sock:/var/run/docker.sock -e AZP_URL=[AzureDevOpsURL] -e AZP_TOKEN=[AzureDevOpsPAT] -e AZP_AGENT_NAME=[AzureDevOpsAgentName] IMAGE:TAG</code></pre>



<p>docker run的指令和<a href="https://tech.uccu.website/2021ironman-day21-build-windows-container-image-for-azure-devops-agent.html" target="_blank" rel="noreferrer noopener">前一篇</a>的大同小異，主要差別在於如何繫結host的docker給container使用。</p>



<p>同樣的環境變數表再貼一次：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" decoding="async" width="1025" height="408" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/4582d3e6-devopsagent-containerenvironmentvariables.png?resize=1025%2C408&#038;ssl=1" alt="" class="wp-image-1265" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/4582d3e6-devopsagent-containerenvironmentvariables.png?w=1025&amp;ssl=1 1025w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/4582d3e6-devopsagent-containerenvironmentvariables.png?resize=300%2C119&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/4582d3e6-devopsagent-containerenvironmentvariables.png?resize=768%2C306&amp;ssl=1 768w" sizes="(max-width: 1025px) 100vw, 1025px" /><figcaption>Azure DevOps Agent所使用的環境變數</figcaption></figure></div>



<p>同樣貼一下執行的結果：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" decoding="async" width="1006" height="669" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/b80fcbf2-devopsagent-runagentinlinuxcontainer.png?resize=1006%2C669&#038;ssl=1" alt="" class="wp-image-1301" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/b80fcbf2-devopsagent-runagentinlinuxcontainer.png?w=1006&amp;ssl=1 1006w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/b80fcbf2-devopsagent-runagentinlinuxcontainer.png?resize=300%2C200&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/b80fcbf2-devopsagent-runagentinlinuxcontainer.png?resize=768%2C511&amp;ssl=1 768w" sizes="(max-width: 1006px) 100vw, 1006px" /></figure></div>



<p>還有Agent Pools裡的列表和Agent的Capabilities：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="793" height="344" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/4e5fe0f5-agentpools-default-linuxcontaineragent.png?resize=793%2C344&#038;ssl=1" alt="" class="wp-image-1304" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/4e5fe0f5-agentpools-default-linuxcontaineragent.png?w=793&amp;ssl=1 793w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/4e5fe0f5-agentpools-default-linuxcontaineragent.png?resize=300%2C130&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/4e5fe0f5-agentpools-default-linuxcontaineragent.png?resize=768%2C333&amp;ssl=1 768w" sizes="auto, (max-width: 793px) 100vw, 793px" /></figure></div>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="784" height="927" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/7b7c07bc-agentpools-default-linuxcontaineragent-capabilities.png?resize=784%2C927&#038;ssl=1" alt="" class="wp-image-1307" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/7b7c07bc-agentpools-default-linuxcontaineragent-capabilities.png?w=784&amp;ssl=1 784w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/7b7c07bc-agentpools-default-linuxcontaineragent-capabilities.png?resize=254%2C300&amp;ssl=1 254w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/7b7c07bc-agentpools-default-linuxcontaineragent-capabilities.png?resize=768%2C908&amp;ssl=1 768w" sizes="auto, (max-width: 784px) 100vw, 784px" /></figure></div>



<p>其它和前一篇的內容沒什麼太大的差別，至於Linux VM的部份意思差不多，所以就不再另外弄一篇安裝在Linux VM裡的文章了</p>
<p>這篇文章 <a href="https://tech.uccu.website/2021ironman-day22-build-linux-container-image-for-azure-devops-agent.html">【2021鐵人賽】建立自管的Azure DevOps Agent(Linux Container agent)</a> 最早出現於 <a href="https://tech.uccu.website">泰克哪裡去</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tech.uccu.website/2021ironman-day22-build-linux-container-image-for-azure-devops-agent.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1292</post-id>	</item>
		<item>
		<title>【2021鐵人賽】建立自管的Azure DevOps Agent(Windows Container agent)</title>
		<link>https://tech.uccu.website/2021ironman-day21-build-windows-container-image-for-azure-devops-agent.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=2021ironman-day21-build-windows-container-image-for-azure-devops-agent</link>
					<comments>https://tech.uccu.website/2021ironman-day21-build-windows-container-image-for-azure-devops-agent.html#respond</comments>
		
		<dc:creator><![CDATA[鳴人]]></dc:creator>
		<pubDate>Sun, 03 Oct 2021 11:58:42 +0000</pubDate>
				<category><![CDATA[2021鐵人賽]]></category>
		<category><![CDATA[Azure DevOps]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[iThome鐵人賽]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[資訊科技]]></category>
		<category><![CDATA[2021ironman]]></category>
		<category><![CDATA[azure devops]]></category>
		<category><![CDATA[container]]></category>
		<category><![CDATA[docker]]></category>
		<guid isPermaLink="false">https://tech.uccu.website/?p=1235</guid>

					<description><![CDATA[<p>這篇延續前一篇在Windows VM中安裝Azure DevOps Agent的內容，講解了如何讓Agent在Windows Container中執行，從基底映像檔的差異到挑選適合的映像檔在Dockerfile中使用，也示範如何將Host中Docker提供給Container使用。</p>
<p>這篇文章 <a href="https://tech.uccu.website/2021ironman-day21-build-windows-container-image-for-azure-devops-agent.html">【2021鐵人賽】建立自管的Azure DevOps Agent(Windows Container agent)</a> 最早出現於 <a href="https://tech.uccu.website">泰克哪裡去</a>。</p>
]]></description>
										<content:encoded><![CDATA[
<p><a href="https://tech.uccu.website/2021ironman-day20-setup-azure-devops-agent-on-windows-vm.html" target="_blank" rel="noreferrer noopener">前一篇</a>提到了在Windows VM中安裝Azure DevOps Agent，步驟非常的簡單，不過Azure DevOps Agent也可以在Container內執行，這一篇就來看看如何在Windows Container內執行Azure DevOps Agent。(如果需要Windows Server安裝Docker的方式請看<a href="https://tech.uccu.website/install-docker-on-windows-server.html" target="_blank" rel="noreferrer noopener">這篇文章</a>)</p>



<p>首先，在Windows Container的部份有些基本的知識需要了解，那就是Windows Container區分不同的基底映像類型(Base Image)，分為Windows、Windows Server、Windows Server Core、Nano Server四種，越前面的映像檔大小所佔的容量越大，包含的功能越多，越後面的則越小，所包含的功能也越少。(參考官方文件：<a href="https://docs.microsoft.com/zh-tw/virtualization/windowscontainers/manage-containers/container-base-images" target="_blank" rel="noreferrer noopener">中文</a>/<a href="https://docs.microsoft.com/en-us/virtualization/windowscontainers/manage-containers/container-base-images" target="_blank" rel="noreferrer noopener">英文</a>)</p>



<p>另外就是Windows Container的隔離模式(Isolation  Modes)，分為Process和Hyper-V隔離這兩種，在Windows Server上執行的Windows Container預設以Process隔離方式執行，在Windows 10執行的Windows Container則預設以Hyper-V隔離方式執行。(參考官方文件：<a href="https://docs.microsoft.com/zh-tw/virtualization/windowscontainers/manage-containers/hyperv-container" target="_blank" rel="noreferrer noopener">中文</a>/<a href="https://docs.microsoft.com/en-us/virtualization/windowscontainers/manage-containers/hyperv-container" target="_blank" rel="noreferrer noopener">英文</a>)</p>



<p>在上面這兩個不同的差異之下，選擇建立Windows Container Image就會有很多的選擇，這牽涉到執行Container的主機(Host)所使用的是哪一個版本的OS，不同版本之間的相容性會有所差異，例如：Windows Server 2019與Windows Server 20H2這兩個版本的OS相容性：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="574" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/e7ee6766-oscompatibility-winserver2019.png?resize=1024%2C574&#038;ssl=1" alt="" class="wp-image-1238" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/e7ee6766-oscompatibility-winserver2019.png?w=1024&amp;ssl=1 1024w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/e7ee6766-oscompatibility-winserver2019.png?resize=300%2C168&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/e7ee6766-oscompatibility-winserver2019.png?resize=768%2C431&amp;ssl=1 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption>Windows Server 2019的OS相容性</figcaption></figure></div>



<div class="wp-block-image"><figure class="aligncenter size-large"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="573" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/d95ace76-oscompatibility-winserver20h2-1024x573.png?resize=1024%2C573&#038;ssl=1" alt="" class="wp-image-1241" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/d95ace76-oscompatibility-winserver20h2.png?resize=1024%2C573&amp;ssl=1 1024w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/d95ace76-oscompatibility-winserver20h2.png?resize=300%2C168&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/d95ace76-oscompatibility-winserver20h2.png?resize=768%2C430&amp;ssl=1 768w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/d95ace76-oscompatibility-winserver20h2.png?w=1031&amp;ssl=1 1031w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption>Windows Server 20H2的OS相容性</figcaption></figure></div>



<p>從上面兩張圖可以看到Windows Server 2019的Host可以支援以Windows Server 2019為基底的Container Image以Process隔離模式執行，若是以Hyper-V隔離模式執行，則是可以支援Windows Server 2019以下的版本。同樣的，Windows Server 20H2的Host可以支援同為Windows Server 20H2的Image以Process隔離模式執行，Hyper-V的隔離模式則是與Host相同版本以下的都能夠支援。</p>



<p>換成是Windows 10作為Host的話，支援性又有不同的差異：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1015" height="566" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/a65d2b83-oscompatibility-win10_1909.png?resize=1015%2C566&#038;ssl=1" alt="" class="wp-image-1244" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/a65d2b83-oscompatibility-win10_1909.png?w=1015&amp;ssl=1 1015w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/a65d2b83-oscompatibility-win10_1909.png?resize=300%2C167&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/a65d2b83-oscompatibility-win10_1909.png?resize=768%2C428&amp;ssl=1 768w" sizes="auto, (max-width: 1015px) 100vw, 1015px" /><figcaption>Windows 10 1909版本的OS相容性</figcaption></figure></div>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1016" height="574" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/06a1c852-oscompatibility-win10_2004.png?resize=1016%2C574&#038;ssl=1" alt="" class="wp-image-1247" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/06a1c852-oscompatibility-win10_2004.png?w=1016&amp;ssl=1 1016w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/06a1c852-oscompatibility-win10_2004.png?resize=300%2C169&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/06a1c852-oscompatibility-win10_2004.png?resize=768%2C434&amp;ssl=1 768w" sizes="auto, (max-width: 1016px) 100vw, 1016px" /><figcaption>Windows 10 2004版本的OS相容性</figcaption></figure></div>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1017" height="570" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/530b0e7f-oscompatibility-win10_20h2.png?resize=1017%2C570&#038;ssl=1" alt="" class="wp-image-1250" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/530b0e7f-oscompatibility-win10_20h2.png?w=1017&amp;ssl=1 1017w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/530b0e7f-oscompatibility-win10_20h2.png?resize=300%2C168&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/530b0e7f-oscompatibility-win10_20h2.png?resize=768%2C430&amp;ssl=1 768w" sizes="auto, (max-width: 1017px) 100vw, 1017px" /><figcaption>Windows 10 20H2版本的OS相容性</figcaption></figure></div>



<p>Windows 10的部份可以從上面三張圖看到一點點差異，就是Windows 10的1909版本並不能支援Windows Server任何版本為基底映像檔以Process隔離模式執行，Windows 10的2004版本之後才開始支援與Windows Server相對應的版本映像檔以Process隔離模式執行，但是以Hyper-V隔離模式執行的話則是支援相同版本以下的OS映像檔。</p>



<p>有點複雜，對吧？</p>



<p>簡單來說，要能夠支援以Process隔離模式執行，必須是Container Base Image和Host為相同版本的OS，若是以Hyper-V隔離模式執行，則必須挑選Host OS版本以下製成的Container Image，也就是說Windows Server 2016的選擇性非常少，只能使用同為Windows Server 2016為基底製作的映像檔，越新的OS版本則支援以Hyper-V隔離模式執行的Container Image選擇越多。</p>



<p>更多Windows Container版本相容性的部份可以參考官方文件的說明(<a href="https://docs.microsoft.com/zh-tw/virtualization/windowscontainers/deploy-containers/version-compatibility" target="_blank" rel="noreferrer noopener">中文</a>/<a href="https://docs.microsoft.com/en-us/virtualization/windowscontainers/deploy-containers/version-compatibility" target="_blank" rel="noreferrer noopener">英文</a>)。</p>



<p>回到Azure DevOps Agent，上面說了那麼多，主要是必須考量Agent要執行的任務需要多大的支援與資源，若是只需要能夠以dotnet sdk建置專案，那麼選擇任何一個OS版本的Image應該都可以，只要能夠在Image裡面安裝dotnet sdk即可。</p>



<p>以dotnet sdk這個例子來說，在官方文件「<a href="https://docs.microsoft.com/zh-tw/azure/devops/pipelines/agents/docker?view=azure-devops" target="_blank" rel="noreferrer noopener">在 Docker 中執行自我裝載的代理程式</a>」所提到的Dockerfile範例是使用Windows Server Core 2019的基底映像檔，裡面並沒有安裝dotnet sdk：</p>



<pre class="wp-block-prismatic-blocks"><code class="language-dockerfile">FROM mcr.microsoft.com/windows/servercore:ltsc2019

WORKDIR /azp

COPY start.ps1 .

CMD powershell .\start.ps1</code></pre>



<p>所以要讓Agent可以執行dotnet build的任務，可以選擇使用上面的範例，在Dockerfile中再另外加入安裝dotnet sdk的內容，或是從<a href="https://hub.docker.com/" target="_blank" rel="noreferrer noopener">Docker hub</a>上另外找<a href="https://hub.docker.com/_/microsoft-dotnet-sdk/" target="_blank" rel="noreferrer noopener">微軟官方製作的dotnet sdk映像檔</a>，找到對應的Container Repository與Image tag，例如：「mcr.microsoft.com/dotnet/sdk:5.0-windowsservercore-ltsc2019」這個就是同樣以Windows Server Core 2019為基底的Image，並且安裝了dotnet 5.0 sdk。</p>



<p>從官方文件「<a href="https://docs.microsoft.com/zh-tw/azure/devops/pipelines/agents/docker?view=azure-devops" target="_blank" rel="noreferrer noopener">在 Docker 中執行自我裝載的代理程式</a>」 中的範例可以看得出來，在Container中執行Azure DevOps Agent的關鍵在於下面這段PowerShell內容，將它複製之後以start.ps1儲存在與Dockerfile相同的位置即可：</p>



<pre class="wp-block-prismatic-blocks"><code class="language-powershell">if (-not (Test-Path Env:AZP_URL)) {
  Write-Error &quot;error: missing AZP_URL environment variable&quot;
  exit 1
}

if (-not (Test-Path Env:AZP_TOKEN_FILE)) {
  if (-not (Test-Path Env:AZP_TOKEN)) {
    Write-Error &quot;error: missing AZP_TOKEN environment variable&quot;
    exit 1
  }

  $Env:AZP_TOKEN_FILE = &quot;\azp\.token&quot;
  $Env:AZP_TOKEN | Out-File -FilePath $Env:AZP_TOKEN_FILE
}

Remove-Item Env:AZP_TOKEN

if ((Test-Path Env:AZP_WORK) -and -not (Test-Path $Env:AZP_WORK)) {
  New-Item $Env:AZP_WORK -ItemType directory | Out-Null
}

New-Item &quot;\azp\agent&quot; -ItemType directory | Out-Null

# Let the agent ignore the token env variables
$Env:VSO_AGENT_IGNORE = &quot;AZP_TOKEN,AZP_TOKEN_FILE&quot;

Set-Location agent

Write-Host &quot;1. Determining matching Azure Pipelines agent...&quot; -ForegroundColor Cyan

$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(&quot;:$(Get-Content ${Env:AZP_TOKEN_FILE})&quot;))
$package = Invoke-RestMethod -Headers @{Authorization=(&quot;Basic $base64AuthInfo&quot;)} &quot;$(${Env:AZP_URL})/_apis/distributedtask/packages/agent?platform=win-x64&amp;`$top=1&quot;
$packageUrl = $package[0].Value.downloadUrl

Write-Host $packageUrl

Write-Host &quot;2. Downloading and installing Azure Pipelines agent...&quot; -ForegroundColor Cyan

$wc = New-Object System.Net.WebClient
$wc.DownloadFile($packageUrl, &quot;$(Get-Location)\agent.zip&quot;)

Expand-Archive -Path &quot;agent.zip&quot; -DestinationPath &quot;\azp\agent&quot;

try
{
  Write-Host &quot;3. Configuring Azure Pipelines agent...&quot; -ForegroundColor Cyan

  .\config.cmd --unattended `
    --agent &quot;$(if (Test-Path Env:AZP_AGENT_NAME) { ${Env:AZP_AGENT_NAME} } else { ${Env:computername} })&quot; `
    --url &quot;$(${Env:AZP_URL})&quot; `
    --auth PAT `
    --token &quot;$(Get-Content ${Env:AZP_TOKEN_FILE})&quot; `
    --pool &quot;$(if (Test-Path Env:AZP_POOL) { ${Env:AZP_POOL} } else { &#039;Default&#039; })&quot; `
    --work &quot;$(if (Test-Path Env:AZP_WORK) { ${Env:AZP_WORK} } else { &#039;_work&#039; })&quot; `
    --replace

  Write-Host &quot;4. Running Azure Pipelines agent...&quot; -ForegroundColor Cyan

  .\run.cmd
}
finally
{
  Write-Host &quot;Cleanup. Removing Azure Pipelines agent...&quot; -ForegroundColor Cyan

  .\config.cmd remove --unattended `
    --auth PAT `
    --token &quot;$(Get-Content ${Env:AZP_TOKEN_FILE})&quot;
}</code></pre>



<p>接著就是準備我們要用的Dockerfile，這邊我以dotnet 5.0 sdk的Windows Server Core 2022映像檔為基底，它裡面包含了PowerShell與dotnet 5.0 sdk，並且我還要額外在Image裡面安裝Docker。若是需要dotnet core 3.1與其它OS基底映像檔的部份可以到<a href="https://hub.docker.com/_/microsoft-dotnet-sdk/" target="_blank" rel="noreferrer noopener">Docker hub的頁面</a>上去尋找相關的Tag：</p>



<pre class="wp-block-prismatic-blocks"><code class="language-dockerfile">FROM mcr.microsoft.com/dotnet/sdk:5.0-windowsservercore-ltsc2022

#在這底下加入要額外裝在Docker Image內的程式

SHELL [&quot;powershell&quot;, &quot;-Command&quot;, &quot;$ErrorActionPreference = &#039;Stop&#039;; $ProgressPreference = &#039;SilentlyContinue&#039;;&quot;]

RUN Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force
RUN Install-Module -Name DockerMsftProvider -Repository PSGallery -Force -verbose
RUN Install-Package -Name docker -ProviderName DockerMsftProvider -Force -verbose -ErrorAction SilentlyContinue; exit 0

#===========================================

WORKDIR /azp

COPY start.ps1 .

CMD powershell .\start.ps1</code></pre>



<p>準備好Dockerfile和start.ps1這兩個檔案之後，執行下面的指令建立映像檔：</p>



<pre class="wp-block-prismatic-blocks"><code class="language-docker">docker build -t devopsagent .</code></pre>



<p>完成Build Image的動作之後，透過下面的指令建立一個名為azure-agent的Container：</p>



<pre class="wp-block-prismatic-blocks"><code class="language-docker">docker run --name azure-agent -d -v \.\pipe\docker_engine:\.\pipe\docker_engine -e AZP_URL=[AzureDevOpsURL] -e AZP_TOKEN=[AzureDevOpsPAT] -e AZP_AGENT_NAME=[AzureDevOpsAgentName] IMAGE:TAG</code></pre>



<p>指令中比較特別的地方是透過mount的方式將host的docker轉給container內使用，也就是「-v \.\pipe\docker_engine:\.\pipe\docker_engine」這段，其它的除了IMAGE:TAG是根據上面的docker build所指定的Repository與Tag(預設為latest)之外，環境變數的部份則參考下面這張表：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1025" height="408" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/4582d3e6-devopsagent-containerenvironmentvariables.png?resize=1025%2C408&#038;ssl=1" alt="" class="wp-image-1265" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/4582d3e6-devopsagent-containerenvironmentvariables.png?w=1025&amp;ssl=1 1025w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/4582d3e6-devopsagent-containerenvironmentvariables.png?resize=300%2C119&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/4582d3e6-devopsagent-containerenvironmentvariables.png?resize=768%2C306&amp;ssl=1 768w" sizes="auto, (max-width: 1025px) 100vw, 1025px" /><figcaption>Azure DevOps Agent所使用的環境變數</figcaption></figure></div>



<p>五個環境變數中的最後兩個AZP_POOL、AZP_WORK是選擇性的，只有前三個是必須的，執行之後的結果如下：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="755" height="533" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/2af50f9a-devopsagent-runagentinwindowscontainer.png?resize=755%2C533&#038;ssl=1" alt="" class="wp-image-1268" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/2af50f9a-devopsagent-runagentinwindowscontainer.png?w=755&amp;ssl=1 755w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/2af50f9a-devopsagent-runagentinwindowscontainer.png?resize=300%2C212&amp;ssl=1 300w" sizes="auto, (max-width: 755px) 100vw, 755px" /><figcaption>Azure DevOps Agent執行在Windows Container中</figcaption></figure></div>



<p>從Azure DevOps中的Agent Pools列表中可以看到這個Agent：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="793" height="277" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/6ad9bba5-agentpools-default-wincontaineragent.png?resize=793%2C277&#038;ssl=1" alt="" class="wp-image-1271" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/6ad9bba5-agentpools-default-wincontaineragent.png?w=793&amp;ssl=1 793w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/6ad9bba5-agentpools-default-wincontaineragent.png?resize=300%2C105&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/6ad9bba5-agentpools-default-wincontaineragent.png?resize=768%2C268&amp;ssl=1 768w" sizes="auto, (max-width: 793px) 100vw, 793px" /></figure></div>



<p>進入查看Capabilities的部份也可以看到幾個比較不一樣的資訊，像是ComputerName是Docker產生的隨機名稱，還有docker的資訊：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="790" height="927" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/df70a783-agentpools-default-wincontaineragent-capabilities.png?resize=790%2C927&#038;ssl=1" alt="" class="wp-image-1274" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/df70a783-agentpools-default-wincontaineragent-capabilities.png?w=790&amp;ssl=1 790w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/df70a783-agentpools-default-wincontaineragent-capabilities.png?resize=256%2C300&amp;ssl=1 256w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/df70a783-agentpools-default-wincontaineragent-capabilities.png?resize=768%2C901&amp;ssl=1 768w" sizes="auto, (max-width: 790px) 100vw, 790px" /><figcaption>Azure DevOps Agent執行在Windows Container中的Capabilities資訊</figcaption></figure></div>



<p>至於為什麼需要將host的docker提供給Container中的docker使用，這部份則是為了讓Container中的docker可以共用host上的docker，從Container中的Agent執行docker build所產生的docker image也會儲存在host的docker images裡面，並且可以代替host執行docker run建立新的Container。不過這麼做也是有安全性的風險的，<a href="https://docs.microsoft.com/zh-tw/azure/devops/pipelines/agents/docker?view=azure-devops#use-docker-within-a-docker-container" target="_blank" rel="noreferrer noopener">官方就有提出警告</a>，是否要這麼做則是可以自行思考決定：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1017" height="367" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/7582834f-waring-usedockerindocker.png?resize=1017%2C367&#038;ssl=1" alt="" class="wp-image-1277" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/7582834f-waring-usedockerindocker.png?w=1017&amp;ssl=1 1017w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/7582834f-waring-usedockerindocker.png?resize=300%2C108&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/7582834f-waring-usedockerindocker.png?resize=768%2C277&amp;ssl=1 768w" sizes="auto, (max-width: 1017px) 100vw, 1017px" /></figure></div>



<p>會在這篇文章中這麼做的原因，純粹是為了提供Windows環境將docker轉給Container內使用的指令使用方式，因為這部份在微軟的文件頁面上似乎沒有提到(我忘了之前從哪裡看到的)。</p>
<p>這篇文章 <a href="https://tech.uccu.website/2021ironman-day21-build-windows-container-image-for-azure-devops-agent.html">【2021鐵人賽】建立自管的Azure DevOps Agent(Windows Container agent)</a> 最早出現於 <a href="https://tech.uccu.website">泰克哪裡去</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tech.uccu.website/2021ironman-day21-build-windows-container-image-for-azure-devops-agent.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1235</post-id>	</item>
		<item>
		<title>Windows Container中修改json檔案設定值的方法</title>
		<link>https://tech.uccu.website/how-to-modify-json-file-in-windows-container.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=how-to-modify-json-file-in-windows-container</link>
					<comments>https://tech.uccu.website/how-to-modify-json-file-in-windows-container.html#respond</comments>
		
		<dc:creator><![CDATA[鳴人]]></dc:creator>
		<pubDate>Tue, 24 Nov 2020 09:28:50 +0000</pubDate>
				<category><![CDATA[Windows]]></category>
		<category><![CDATA[appsettings.json]]></category>
		<category><![CDATA[container]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[windows]]></category>
		<guid isPermaLink="false">https://tech.uccu.website/?p=153</guid>

					<description><![CDATA[<p>通常使用到Docker技術執行Container容器都是使用Linux環境，但是Windows環境也可以使用C ... <a title="Windows Container中修改json檔案設定值的方法" class="read-more" href="https://tech.uccu.website/how-to-modify-json-file-in-windows-container.html" aria-label="Read more about Windows Container中修改json檔案設定值的方法">閱讀全文</a></p>
<p>這篇文章 <a href="https://tech.uccu.website/how-to-modify-json-file-in-windows-container.html">Windows Container中修改json檔案設定值的方法</a> 最早出現於 <a href="https://tech.uccu.website">泰克哪裡去</a>。</p>
]]></description>
										<content:encoded><![CDATA[
<p>通常使用到Docker技術執行Container容器都是使用Linux環境，但是Windows環境也可以使用Container，有的時候因為一些考量會需要製作兩套不同環境(Windows &amp; Linux)的Docker Image，所以前面一篇文章提到了如何在<em><a href="https://tech.uccu.website/how-to-modify-json-file-in-linux-container.html" target="_blank" rel="noreferrer noopener">Linux Container中修改json檔案設定值的方法</a></em>，這一篇則是來說明如何在Windows Container中做到一樣的事情。</p>



<p>不同的地方在於，Linux環境中透過額外安裝jq套件來達成修改json檔案的作法，在Windows環境下我們則是使用PowerShell來達成這樣的事情，所以不需要額外安裝任何套件(PowerShell應該都有內建在Windows環境中)。</p>



<span id="more-153"></span>



<p>下面的內容和<em><a href="https://tech.uccu.website/how-to-modify-json-file-in-linux-container.html" target="_blank" rel="noreferrer noopener">Linux Container中修改json檔案設定值的方法</a></em>文章中的內容幾乎一樣，我額外用不同的字型顏色標出不同的地方，以便參考。</p>



<h2 class="wp-block-heading">使用方式</h2>



<p>假設在Dockerfile中定義了<em><strong>ENV&nbsp;LOG_LEVEL=Error</strong></em>，並且appsettings.json檔案中有段Serilog的設定如下：</p>



<pre class="wp-block-prismatic-blocks"><code class="language-json">{
    &quot;Serilog&quot;: {
        &quot;MinimumLevel&quot;: &quot;Debug&quot;,
        &quot;WriteTo&quot;: [
            {
                &quot;Name&quot;: &quot;File&quot;,
                &quot;Args&quot;: {
                    &quot;path&quot;: &quot;MyApp.log&quot;,
                    &quot;outputTemplate&quot;: &quot;{Timestamp:yyyy-MM-dd HH:mm:ss} RequestID:{RequestID} User:{UserID} {RequestPath} {SourceContext} [{Level:u3}] {Message:lj}{NewLine}{Exception}&quot;,
                    &quot;rollingInterval&quot;: &quot;Day&quot;
                }
            }
        ],
        &quot;Enrich&quot;: [ &quot;FromLogContext&quot; ]
    }
}</code></pre>



<p>可以看到在Serilog中有個MinimumLevel屬性設定的是Debug，這個設定會記錄大量的Log記錄，但是有時候在執行container的時候並不想要記錄這麼詳細的資訊，以降低檔案大小，減少儲存空間的耗用時，有個LOG_LEVEL的ENV設定就可以方便的調整設定值。</p>



<p>現在假設有個.Net Core的程式叫MyApp，Build完之後有個MyApp.dll檔案，在Dockerfile中設定了ENV和複製相關的執行檔案之外，還需要一個<span style="color:#0000ff" class="has-inline-color">.ps1檔案(Powershell的副檔名)</span>，假設這個檔案叫做app-init.<span style="color:#0000ff" class="has-inline-color">ps1</span>。</p>



<p>接下來在app-init<span style="color:#0000ff" class="has-inline-color">.ps1</span>檔案中要做下面這幾件事：</p>



<ol class="wp-block-list"><li>判斷container是不是第一次執行，以避免每次都進行修改appsettings.json的動作。</li><li>透過<span style="color:#0000ff" class="has-inline-color">Powershell的Get-Content指令</span>將appsettings.json的內容讀入記憶體。</li><li>找到MinimumLevel屬性，將值修改為LOG_LEVEL這個ENV所設定的值。</li><li>將<span style="color:#0000ff" class="has-inline-color">Powershell</span>修改後的內容儲存為appsettings.temp.json。</li><li>將原本的appsettings.json改名為appsettings.ori.json。</li><li>將前面的appsettings.temp.json改名為appsettings.json。</li><li>產生一個用來判斷是否執行過app-init<span style="color:#0000ff" class="has-inline-color">.ps1</span>的檔案，例如：inited<span style="color:#0000ff" class="has-inline-color">.txt</span>。</li><li>啟動MyApp。</li></ol>



<pre class="wp-block-prismatic-blocks"><code class="language-powershell">Set-Location C:\app

if (Test-Path inited.txt) {
    echo &quot;Powershell already run finished.&quot;
}
else {
    $JsonSettings = Get-Content appsettings.json | ConvertFrom-Json
    $JsonSettings.Serilog.MinimumLevel = &quot;$env:LOG_LEVEL&quot;
    $JsonSettings | ConvertTo-Json -Depth 10 &gt; appsettings.temp.json

    Rename-Item appsettings.json appsettings.ori.json
    Rename-Item appsettings.temp.json appsettings.json
    &quot;Powershell run finished.&quot; &gt; inited.txt
}

dotnet MyApp.dll</code></pre>
<p>這篇文章 <a href="https://tech.uccu.website/how-to-modify-json-file-in-windows-container.html">Windows Container中修改json檔案設定值的方法</a> 最早出現於 <a href="https://tech.uccu.website">泰克哪裡去</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tech.uccu.website/how-to-modify-json-file-in-windows-container.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">153</post-id>	</item>
		<item>
		<title>Linux container中修改json檔案設定值的方法</title>
		<link>https://tech.uccu.website/how-to-modify-json-file-in-linux-container.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=how-to-modify-json-file-in-linux-container</link>
					<comments>https://tech.uccu.website/how-to-modify-json-file-in-linux-container.html#respond</comments>
		
		<dc:creator><![CDATA[鳴人]]></dc:creator>
		<pubDate>Tue, 24 Nov 2020 09:10:21 +0000</pubDate>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[appsettings.json]]></category>
		<category><![CDATA[container]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[linux]]></category>
		<guid isPermaLink="false">https://tech.uccu.website/?p=151</guid>

					<description><![CDATA[<p>現在許多的程式設計都使用了json格式的檔案作為設定檔的儲存格式，可以跨平台在Linux環境執行的.Net C ... <a title="Linux container中修改json檔案設定值的方法" class="read-more" href="https://tech.uccu.website/how-to-modify-json-file-in-linux-container.html" aria-label="Read more about Linux container中修改json檔案設定值的方法">閱讀全文</a></p>
<p>這篇文章 <a href="https://tech.uccu.website/how-to-modify-json-file-in-linux-container.html">Linux container中修改json檔案設定值的方法</a> 最早出現於 <a href="https://tech.uccu.website">泰克哪裡去</a>。</p>
]]></description>
										<content:encoded><![CDATA[
<p>現在許多的程式設計都使用了json格式的檔案作為設定檔的儲存格式，可以跨平台在Linux環境執行的.Net Core也不例外，伴隨著appsettings.json檔案中許多的設定，不管是預設的設定，或是不同開發需求自行加入進去的設定值，全部都是json格式。</p>



<p>為了在docker啟動container的時候可以根據繫結的環境參數(environment, -e)值做出相對應的修改，因此需要有個方便的作法可以在container執行的時候動態修改json檔案。</p>



<p>這一篇文章就來介紹如何在Linux中透過jq套件修改json文件。</p>



<span id="more-151"></span>



<h2 class="wp-block-heading">先決條件</h2>



<p>Container中需要先安裝jq套件，所以必須在Dockerfile中先透過<em>apt-get install -y jq</em>指令(Ubuntu/Debian)安裝jq套件，以便Docker Image中有jq套件可以使用。</p>



<h2 class="wp-block-heading">使用方式</h2>



<p>假設在Dockerfile中定義了<em><strong>ENV&nbsp;LOG_LEVEL=Error</strong></em>，並且appsettings.json檔案中有段Serilog的設定如下：</p>



<pre class="wp-block-prismatic-blocks"><code class="language-json">{
    &quot;Serilog&quot;: {
        &quot;MinimumLevel&quot;: &quot;Debug&quot;,
        &quot;WriteTo&quot;: [
            {
                &quot;Name&quot;: &quot;File&quot;,
                &quot;Args&quot;: {
                    &quot;path&quot;: &quot;MyApp.log&quot;,
                    &quot;outputTemplate&quot;: &quot;{Timestamp:yyyy-MM-dd HH:mm:ss} RequestID:{RequestID} User:{UserID} {RequestPath} {SourceContext} [{Level:u3}] {Message:lj}{NewLine}{Exception}&quot;,
                    &quot;rollingInterval&quot;: &quot;Day&quot;
                }
            }
        ],
        &quot;Enrich&quot;: [ &quot;FromLogContext&quot; ]
    }
}</code></pre>



<p>可以看到在Serilog中有個MinimumLevel屬性設定的是Debug，這個設定會記錄大量的Log記錄，但是有時候在執行container的時候並不想要記錄這麼詳細的資訊，以降低檔案大小，減少儲存空間的耗用時，有個LOG_LEVEL的ENV設定就可以方便的調整設定值。</p>



<p>現在假設有個.Net Core的程式叫MyApp，Build完之後有個MyApp.dll檔案，在Dockerfile中設定了ENV和複製相關的執行檔案之外，還需要一個.sh檔案(Linux中的Shell檔，相當於Windows的.cmd或.bat)，假設這個檔案叫做app-init.sh。</p>



<p>接下來在app-init.sh檔案中要做下面這幾件事：</p>



<ol class="wp-block-list"><li>判斷container是不是第一次執行，以避免每次都進行修改appsettings.json的動作。</li><li>透過jq套件將appsettings.json的內容讀入記憶體。</li><li>找到MinimumLevel屬性，將值修改為LOG_LEVEL這個ENV所設定的值。</li><li>將jq套件修改後的內容儲存為appsettings.temp.json。</li><li>將原本的appsettings.json改名為appsettings.ori.json。</li><li>將前面的appsettings.temp.json改名為appsettings.json。</li><li>產生一個用來判斷是否執行過app-init.sh的檔案，例如：inited。</li><li>啟動MyApp。</li></ol>



<p>假設Dockerfile中設定的WORKDIR是/app，第7點的檔案是放在/app/inited，那麼app-init.sh的程式碼內容大概會是下面這個樣子：</p>



<pre class="wp-block-prismatic-blocks"><code class="language-bash">if [ -f &quot;/app/inited&quot; ]; then
    echo &quot;Container inited, skip this shell.&quot;
else
    cat appsettings.json #這行只是先輸出原本的設定值，用來查看用的
    jq &#039;.Serilog.MinimumLevel=env.LOG_LEVEL&#039; appsettings.json &gt; appsettings.temp.json

    cat appsettings.temp.json #查看儲存的檔案內容

    mv appsettings.json appsettings.ori.json #第5點，將原本的設定檔改名
    mv appsettings.temp.json appsettings.json #第6點，將jq儲存的暫存檔改為正式檔名

    echo &quot;Container inited.&quot; &gt; /app/inited #第7點，產生判斷是否init過的檔案
fi

dotnet MyApp.dll #第8點，啟動MyApp</code></pre>



<p>透過上面的app-init.sh檔案，在Container第一次執行的時候就會根據設定的內容修改appsettings.json檔案，產生的inited檔案可以避免container restart之後重複執行init的動作。</p>



<p>透過這樣的技巧，也可以修改appsettings.json中的資料庫連線字串，如果是像Serilog底下的WriteTo屬性是陣列(集合)型式的，則是用[0]、[1]這樣的方式設定，範例如下：</p>



<pre class="wp-block-prismatic-blocks"><code class="language-bash">jq &#039;.Serilog.MinimumLevel=env.LOG_LEVEL&#039; appsettings.json | \
jq &#039;.Serilog.WriteTo[0].Args.rollingInterval=env.LOG_ROLLING_INTERVAL&#039;  &gt; appsettings.temp.json</code></pre>
<p>這篇文章 <a href="https://tech.uccu.website/how-to-modify-json-file-in-linux-container.html">Linux container中修改json檔案設定值的方法</a> 最早出現於 <a href="https://tech.uccu.website">泰克哪裡去</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tech.uccu.website/how-to-modify-json-file-in-linux-container.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">151</post-id>	</item>
		<item>
		<title>同一台電腦可執行Windows與Linux Container？在WSL2安裝原生Docker環境</title>
		<link>https://tech.uccu.website/how-to-install-docker-on-wsl2.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=how-to-install-docker-on-wsl2</link>
					<comments>https://tech.uccu.website/how-to-install-docker-on-wsl2.html#respond</comments>
		
		<dc:creator><![CDATA[鳴人]]></dc:creator>
		<pubDate>Thu, 10 Sep 2020 09:10:50 +0000</pubDate>
				<category><![CDATA[Docker]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[container]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[wsl]]></category>
		<guid isPermaLink="false">https://tech.uccu.website/?p=70</guid>

					<description><![CDATA[<p>如果想要在同一台電腦中既可以執行Windows Container，又可以執行Linux Container， ... <a title="同一台電腦可執行Windows與Linux Container？在WSL2安裝原生Docker環境" class="read-more" href="https://tech.uccu.website/how-to-install-docker-on-wsl2.html" aria-label="Read more about 同一台電腦可執行Windows與Linux Container？在WSL2安裝原生Docker環境">閱讀全文</a></p>
<p>這篇文章 <a href="https://tech.uccu.website/how-to-install-docker-on-wsl2.html">同一台電腦可執行Windows與Linux Container？在WSL2安裝原生Docker環境</a> 最早出現於 <a href="https://tech.uccu.website">泰克哪裡去</a>。</p>
]]></description>
										<content:encoded><![CDATA[
<p>如果想要在同一台電腦中既可以執行Windows Container，又可以執行Linux Container，以便測試程式在不同環境之下執行的結果或是設定值的差異，該如何達到這樣的需求呢？</p>



<p>答案就是：利用Windows中的Linux子系統(Windows Subsystem for Linux, WSL)。</p>



<p>透過WSL安裝Linux子系統之後，可以在Linux子系統中安裝原生的Docker執行環境，在Windows環境中則是安裝Docker Desktop並且切換到使用Windows Container，這樣一來就可以在Windows環境執行Windows Container，Linux子系統中執行Linux Container了。</p>



<p><em>註：WSL是Windows 10的功能，版本又分為Version 1(WSL)與Version 2(WSL2)，WSL2只能在Windows 10 2004版(組建19041以上)執行。(<a href="https://docs.microsoft.com/zh-tw/windows/wsl/" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener nofollow">參考官方wsl文件說明</a>)</em></p>



<p>在開始之前，先輸入<code class="language-bash">wsl -l -v</code>查看一下系統內安裝的Linux子系統是執行在哪一個版本(1或2)。<br>在Linux子系統中要執行原生的Docker，只能在Version 2的版本(WSL2)。</p>



<figure class="wp-block-image size-large"><img data-recalc-dims="1" loading="lazy" decoding="async" width="657" height="229" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/3955add2-image.png?resize=657%2C229&#038;ssl=1" alt="" class="wp-image-71" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/3955add2-image.png?w=657&amp;ssl=1 657w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/3955add2-image.png?resize=300%2C105&amp;ssl=1 300w" sizes="auto, (max-width: 657px) 100vw, 657px" /><figcaption>使用<code>wsl -l -v</code>查看系統中 Linux子系統執行的版本</figcaption></figure>



<span id="more-70"></span>



<p>先輸入<code class="language-bash">docker info</code>確認系統中沒有安裝docker。</p>



<figure class="wp-block-image size-large"><img data-recalc-dims="1" loading="lazy" decoding="async" width="943" height="247" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/7f0c8bfc-image.png?resize=943%2C247&#038;ssl=1" alt="" class="wp-image-72" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/7f0c8bfc-image.png?w=943&amp;ssl=1 943w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/7f0c8bfc-image.png?resize=300%2C79&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/7f0c8bfc-image.png?resize=768%2C201&amp;ssl=1 768w" sizes="auto, (max-width: 943px) 100vw, 943px" /><figcaption>輸入<code>docker info</code>確認系統中確實沒有安裝docker</figcaption></figure>



<p>接著，根據官方的安裝指引將Docker Engine安裝到Linux子系統中：</p>



<ul class="wp-block-list"><li>Ubuntu：<a aria-label="undefined (opens in a new tab)" href="https://docs.docker.com/engine/install/ubuntu/" target="_blank" rel="noreferrer noopener nofollow">https://docs.docker.com/engine/install/ubuntu/</a></li><li>Debian：<a aria-label="undefined (opens in a new tab)" href="https://docs.docker.com/engine/install/debian/" target="_blank" rel="noreferrer noopener nofollow">https://docs.docker.com/engine/install/debian/</a></li><li>CentOS：<a aria-label="undefined (opens in a new tab)" href="https://docs.docker.com/engine/install/centos/" target="_blank" rel="noreferrer noopener nofollow">https://docs.docker.com/engine/install/centos/</a></li><li>Fedora：<a href="https://docs.docker.com/engine/install/fedora/" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener nofollow">https://docs.docker.com/engine/install/fedora/</a></li></ul>



<h4 class="wp-block-heading">更新系統中的套件</h4>



<p>先輸入<code class="language-bash">sudo apt-get update</code>更新系統中的套件。</p>



<figure class="wp-block-image size-large"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="906" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/4afb5ecb-image-1024x906.png?resize=1024%2C906&#038;ssl=1" alt="" class="wp-image-73" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/4afb5ecb-image.png?resize=1024%2C906&amp;ssl=1 1024w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/4afb5ecb-image.png?resize=300%2C265&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/4afb5ecb-image.png?resize=768%2C680&amp;ssl=1 768w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/4afb5ecb-image.png?w=1269&amp;ssl=1 1269w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption>先輸入<code>sudo apt-get</code>更新系統中的套件</figcaption></figure>



<h4 class="wp-block-heading">安裝需要的套件</h4>



<p>再輸入下列指令安裝docker需要的其它套件：</p>



<pre class="wp-block-prismatic-blocks"><code class="language-bash">sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common</code></pre>



<p><em>註：「\」符號是Linux指令的換行連接符號，用來將較長的指令換行輸入，實際上在系統中仍然是組合成一整行的指令，因此也可以將上面的指令直接輸入成一行。(記得拿掉「\」符號)</em></p>



<figure class="wp-block-image size-large"><img data-recalc-dims="1" loading="lazy" decoding="async" width="827" height="175" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/5ee778d6-image.png?resize=827%2C175&#038;ssl=1" alt="" class="wp-image-74" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/5ee778d6-image.png?w=827&amp;ssl=1 827w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/5ee778d6-image.png?resize=300%2C63&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/5ee778d6-image.png?resize=768%2C163&amp;ssl=1 768w" sizes="auto, (max-width: 827px) 100vw, 827px" /><figcaption>安裝docker前需要安裝的套件</figcaption></figure>



<p>安裝上述幾個套件的過程中會碰到詢問y/n的問題，通常是告知會使用多少磁碟空間，輸入y繼續安裝就行了。</p>



<figure class="wp-block-image size-large"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="749" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/6958cf39-image-1024x749.png?resize=1024%2C749&#038;ssl=1" alt="" class="wp-image-75" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/6958cf39-image.png?resize=1024%2C749&amp;ssl=1 1024w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/6958cf39-image.png?resize=300%2C220&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/6958cf39-image.png?resize=768%2C562&amp;ssl=1 768w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/6958cf39-image.png?w=1499&amp;ssl=1 1499w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption>安裝apt-transport-https、ca-certificates、curl、gnupg-agent、software-properties-common套件與其相依的套件</figcaption></figure>



<h4 class="wp-block-heading">取得GPG Key</h4>



<p>接下來取得docker的GPG key：</p>



<pre class="wp-block-prismatic-blocks"><code class="language-bash">curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -</code></pre>



<p><em>註：「|」符號是Linux中的命令管線符號，用來將前一個命令執行的結果送到下一個命令的輸入。</em></p>



<figure class="wp-block-image size-large"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="39" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/88c5a78e-image-1024x39.png?resize=1024%2C39&#038;ssl=1" alt="" class="wp-image-76" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/88c5a78e-image.png?resize=1024%2C39&amp;ssl=1 1024w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/88c5a78e-image.png?resize=300%2C11&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/88c5a78e-image.png?resize=768%2C29&amp;ssl=1 768w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/88c5a78e-image.png?w=1505&amp;ssl=1 1505w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption>透過curl取得docker的GPG key</figcaption></figure>



<p>接下來<strong>這一步可以跳過</strong>，只是用來驗證剛才取得的GPG key是否正確。</p>



<pre class="wp-block-prismatic-blocks"><code class="language-bash">sudo apt-key fingerprint 0EBFCD88</code></pre>



<p>輸入完之後會看到下面<code>9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88</code>的內容。</p>



<figure class="wp-block-image size-large"><img data-recalc-dims="1" loading="lazy" decoding="async" width="947" height="145" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/eb1ab3ee-image.png?resize=947%2C145&#038;ssl=1" alt="" class="wp-image-77" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/eb1ab3ee-image.png?w=947&amp;ssl=1 947w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/eb1ab3ee-image.png?resize=300%2C46&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/eb1ab3ee-image.png?resize=768%2C118&amp;ssl=1 768w" sizes="auto, (max-width: 947px) 100vw, 947px" /><figcaption>驗證取得的GPG key</figcaption></figure>



<h4 class="wp-block-heading">加入套件存放庫(Repository)</h4>



<p>接下來將docker官方的套件存放庫(repository)加入到Linux子系統中，這樣才能夠安裝docker engine：</p>



<pre class="wp-block-prismatic-blocks"><code class="language-bash">sudo add-apt-repository \
&quot;deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable&quot;</code></pre>



<figure class="wp-block-image size-large"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="319" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/a5c90088-image-1024x319.png?resize=1024%2C319&#038;ssl=1" alt="" class="wp-image-80" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/a5c90088-image.png?resize=1024%2C319&amp;ssl=1 1024w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/a5c90088-image.png?resize=300%2C94&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/a5c90088-image.png?resize=768%2C240&amp;ssl=1 768w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/a5c90088-image.png?w=1087&amp;ssl=1 1087w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption>將docker的套件庫加入到系統中</figcaption></figure>



<p><em>小提示：如果你發現你的網址輸入錯誤．也就是在輸入指令之後下面的訊息有顯示Err的字樣，那麼可以編輯套件庫清單的設定檔，將錯誤的網址修正或移除重新加入。</em>(<a aria-label="undefined (opens in a new tab)" href="https://unix.stackexchange.com/questions/219341/how-to-apt-delete-repository" target="_blank" rel="noreferrer noopener nofollow">參考來源</a>)</p>



<pre class="wp-block-prismatic-blocks"><code class="language-bash">sudo nano /etc/apt/sources.list</code></pre>



<h4 class="wp-block-heading">安裝Docker Engine</h4>



<p>輸入下面兩行指令安裝Docker Engine，第一行是更新套件指令，第二行則是安裝Docker的指令</p>



<pre class="wp-block-prismatic-blocks"><code class="language-bash">sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io</code></pre>



<p>安裝過程中會有個磁碟空間耗用的問題，輸入y就能繼續。<br>接著會碰到下面的問題，是詢問grub-pc套件要裝在哪一個磁碟分割：</p>



<figure class="wp-block-image size-large"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="423" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/f688bcfe-image-1024x423.png?resize=1024%2C423&#038;ssl=1" alt="" class="wp-image-81" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/f688bcfe-image.png?resize=1024%2C423&amp;ssl=1 1024w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/f688bcfe-image.png?resize=300%2C124&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/f688bcfe-image.png?resize=768%2C317&amp;ssl=1 768w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/f688bcfe-image.png?resize=1536%2C635&amp;ssl=1 1536w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/f688bcfe-image.png?w=1619&amp;ssl=1 1619w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption>選擇grub-pc套件要安裝的目標</figcaption></figure>



<p>grub-pc應該是一個啟動管理的套件，不太確定是上面哪個套件相依的需求，以上圖來看，Linux子系統抓到三個(實際上只有sda、sdb兩個)容量大小相同的項目。<br>透過空白鍵可以選擇/取消，想知道sda、sdb分別是什麼的話，可以再另外開一個cmd或powershell視窗，輸入wsl透過另外一個terminal進入查看：</p>



<figure class="wp-block-image size-large"><img data-recalc-dims="1" loading="lazy" decoding="async" width="867" height="565" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/b287d344-image.png?resize=867%2C565&#038;ssl=1" alt="" class="wp-image-82" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/b287d344-image.png?w=867&amp;ssl=1 867w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/b287d344-image.png?resize=300%2C196&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/b287d344-image.png?resize=768%2C500&amp;ssl=1 768w" sizes="auto, (max-width: 867px) 100vw, 867px" /><figcaption>透過<code>df -h</code>、<code>lsblk</code>、<code>sudo blkid</code>指令查看磁碟資訊</figcaption></figure>



<p>從上面可以發現sda、sdb其實是一樣的，只是檔案系統實際上掛載在sdb項目，所以選擇sda、sdb也許都可以，不過實際上選擇第一個sda項目的時候，安裝到一半會出現下面的錯誤訊息：</p>



<figure class="wp-block-image size-large"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="299" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/71a5ac8f-image-1024x299.png?resize=1024%2C299&#038;ssl=1" alt="" class="wp-image-83" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/71a5ac8f-image.png?resize=1024%2C299&amp;ssl=1 1024w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/71a5ac8f-image.png?resize=300%2C88&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/71a5ac8f-image.png?resize=768%2C224&amp;ssl=1 768w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/71a5ac8f-image.png?w=1223&amp;ssl=1 1223w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption>無法安裝在sda</figcaption></figure>



<p>既然無法安裝在sda，那麼就不要霸王硬上弓硬是要安裝在sda，所以選擇No之後，回到上面的選單項目，將sda取消，選擇第二個sdb試試。<br>沒有再出現上面無法安裝詢問是否要霸王硬上弓的問題，順利安裝完成。</p>



<p>輸入<code>docker info</code>查看安裝的結果，只顯示client資訊，server資訊則是無法連線，其實這只是docker service沒有啟動的關係。</p>



<figure class="wp-block-image size-large"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="152" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/5682d84c-image-1024x152.png?resize=1024%2C152&#038;ssl=1" alt="" class="wp-image-84" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/5682d84c-image.png?resize=1024%2C152&amp;ssl=1 1024w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/5682d84c-image.png?resize=300%2C45&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/5682d84c-image.png?resize=768%2C114&amp;ssl=1 768w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/5682d84c-image.png?w=1351&amp;ssl=1 1351w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>輸入<code>sudo service docker start</code>啟動docker服務，再次輸入<code>docker info</code>查看docker的資訊卻發現…</p>



<figure class="wp-block-image size-large"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="149" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/afb2eb9d-image-1024x149.png?resize=1024%2C149&#038;ssl=1" alt="" class="wp-image-85" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/afb2eb9d-image.png?resize=1024%2C149&amp;ssl=1 1024w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/afb2eb9d-image.png?resize=300%2C44&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/afb2eb9d-image.png?resize=768%2C112&amp;ssl=1 768w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/afb2eb9d-image.png?resize=1536%2C224&amp;ssl=1 1536w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/afb2eb9d-image.png?w=1559&amp;ssl=1 1559w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>看起來和上面那張截圖滿像的，不過最後有個關鍵字是「permission denied」。<br>既然如此，那使用sudo執行看看呢？(<code>sudo docker info</code>)</p>



<figure class="wp-block-image size-large"><img data-recalc-dims="1" loading="lazy" decoding="async" width="868" height="1024" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/9cd58616-image-868x1024.png?resize=868%2C1024&#038;ssl=1" alt="" class="wp-image-87" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/9cd58616-image.png?resize=868%2C1024&amp;ssl=1 868w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/9cd58616-image.png?resize=254%2C300&amp;ssl=1 254w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/9cd58616-image.png?resize=768%2C906&amp;ssl=1 768w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/9cd58616-image.png?w=1123&amp;ssl=1 1123w" sizes="auto, (max-width: 868px) 100vw, 868px" /></figure>



<p>Bingo，能夠正常查看到docker的資訊了！</p>



<p>不過這樣每次要執行docker相關的指令都要輸入sudo有點麻煩，所以接著可以利用下面的指令，將docker加入特定的用戶群：</p>



<pre class="wp-block-prismatic-blocks"><code class="language-bash">sudo usermod -aG docker 帳號</code></pre>



<p>輸入完上面的指令之後，如果直接再次輸入docker info想要試試是否有效，會得到令人失望的結果。主要是因為當下使用的terminal沒有登出再重新登入取得最新的資訊，只要退出terminal之後再重新執行就可以正常了。</p>



<figure class="wp-block-image size-large"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="669" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/28de246d-image-1024x669.png?resize=1024%2C669&#038;ssl=1" alt="" class="wp-image-88" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/28de246d-image.png?resize=1024%2C669&amp;ssl=1 1024w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/28de246d-image.png?resize=300%2C196&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/28de246d-image.png?resize=768%2C502&amp;ssl=1 768w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/28de246d-image.png?resize=1536%2C1003&amp;ssl=1 1536w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/28de246d-image.png?w=1557&amp;ssl=1 1557w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption>輸入完<code>sudo usermod -aG docker &lt;em&gt;帳號&lt;/em&gt;</code>，需要離開wsl再重新進入才會生效</figcaption></figure>



<p>OK，這下子終於將docker順利安裝在WSL2裡面啦~</p>



<p>從下面的截圖也可以發現，在wsl裡面查看docker info和windows底下查看docker info的差異，證明兩個docker環境是彼此分開獨立的喔！</p>



<p>PS.Windows環境安裝Docker Desktop並且切換到Windows Container模式了，這樣一來就可以在一台電腦中同時執行Linux Container與Windows Container了。</p>



<figure class="wp-block-image size-large"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="787" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/d696fac4-image-1024x787.png?resize=1024%2C787&#038;ssl=1" alt="" class="wp-image-90" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/d696fac4-image.png?resize=1024%2C787&amp;ssl=1 1024w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/d696fac4-image.png?resize=300%2C230&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/d696fac4-image.png?resize=768%2C590&amp;ssl=1 768w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/d696fac4-image.png?resize=1536%2C1180&amp;ssl=1 1536w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/08/d696fac4-image.png?w=1725&amp;ssl=1 1725w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption>同一台電腦中同時執行Windows Docker與Linux Docker環境</figcaption></figure>
<p>這篇文章 <a href="https://tech.uccu.website/how-to-install-docker-on-wsl2.html">同一台電腦可執行Windows與Linux Container？在WSL2安裝原生Docker環境</a> 最早出現於 <a href="https://tech.uccu.website">泰克哪裡去</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tech.uccu.website/how-to-install-docker-on-wsl2.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">70</post-id>	</item>
		<item>
		<title>Windows 10 Home家用版安裝Hyper-V與Docker</title>
		<link>https://tech.uccu.website/windows10-home-install-hyperv-docker.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=windows10-home-install-hyperv-docker</link>
					<comments>https://tech.uccu.website/windows10-home-install-hyperv-docker.html#respond</comments>
		
		<dc:creator><![CDATA[鳴人]]></dc:creator>
		<pubDate>Tue, 19 May 2020 08:05:08 +0000</pubDate>
				<category><![CDATA[Docker]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[container]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[hyper-v]]></category>
		<category><![CDATA[windows 10 home]]></category>
		<category><![CDATA[wsl]]></category>
		<guid isPermaLink="false">https://tech.uccu.website/?p=30</guid>

					<description><![CDATA[<p>公司一開始配的電腦是Acer的套裝電腦，裡面搭配的是Windows 10 Home版，作為一個開發者，Home ... <a title="Windows 10 Home家用版安裝Hyper-V與Docker" class="read-more" href="https://tech.uccu.website/windows10-home-install-hyperv-docker.html" aria-label="Read more about Windows 10 Home家用版安裝Hyper-V與Docker">閱讀全文</a></p>
<p>這篇文章 <a href="https://tech.uccu.website/windows10-home-install-hyperv-docker.html">Windows 10 Home家用版安裝Hyper-V與Docker</a> 最早出現於 <a href="https://tech.uccu.website">泰克哪裡去</a>。</p>
]]></description>
										<content:encoded><![CDATA[
<p>公司一開始配的電腦是Acer的套裝電腦，裡面搭配的是Windows 10 Home版，作為一個開發者，Home版本的功能實在是不太符合需求，因為預設應該是沒有Hyper-V功能，如果要安裝Docker的話，也只能安裝Client工具…</p>



<p>不太想要動到OS重灌這一招，想到之前似乎有試過(看到)在Windows 10 Home版安裝Hyper-V與WSL，不過因為很久沒有寫部落格記錄，有些問題解決之後就沒有記錄，所以趁著這次解決這個問題並且將部落格從幾次亂搞之後最近放到Google Cloud Run上面執行，一併將這些操作記錄下來。</p>



<span id="more-30"></span>



<p class="has-text-align-left">首先，Windows 10 Home版打開控制台「程式和功能」中的「Windows 功能」應該不會有「Hyper-V平台」、「適用於 Linux 的 Windows 子系統」兩個選項。</p>



<p class="has-text-align-center"><img data-recalc-dims="1" loading="lazy" decoding="async" width="600" height="400" class="wp-image-33" style="width: 600px;" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/05/b94afa4b-windows10-home-windows-features.png?resize=600%2C400&#038;ssl=1" alt="Windows 10 Home家用版Windows功能" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/05/b94afa4b-windows10-home-windows-features.png?w=731&amp;ssl=1 731w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/05/b94afa4b-windows10-home-windows-features.png?resize=300%2C200&amp;ssl=1 300w" sizes="auto, (max-width: 600px) 100vw, 600px" /></p>



<p>從<a href="https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/reference/hyper-v-requirements">Windows 10 Hyper-V System Requirements</a>的頁面說明中也有下面這段，明確表明Windows 10 Home的版本不能安裝。</p>



<p>The Hyper-V role&nbsp;<strong>cannot</strong>&nbsp;be installed on:</p>



<ul class="wp-block-list"><li>Windows 10 Home</li><li>Windows 10 Mobile</li><li>Windows 10 Mobile Enterprise</li></ul>



<p>不過這個其實有秘技可以讓Hyper-V安裝在Windows 10 Home，只需要將下面這段指令貼在記事本上，並且以.bat的副檔名儲存後透過管理員權限執行即可。</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>pushd &#8220;%~dp0&#8221;<br>dir /b %SystemRoot%\servicing\Packages*Hyper-V*.mum &gt;hyper-v.txt<br>for /f %%i in (&#8216;findstr /i . hyper-v.txt 2^&gt;nul&#8217;) do dism /online /norestart /add-package:&#8221;%SystemRoot%\servicing\Packages\%%i&#8221;<br>del hyper-v.txt<br>Dism /online /enable-feature /featurename:Microsoft-Hyper-V -All /LimitAccess /ALL<br>pause</p></blockquote>



<p>如果也想要安裝Container功能的話，同樣將下面這段指令以.bat儲存後透過管理員權限執行。</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>pushd &#8220;%~dp0&#8221;<br>dir /b %SystemRoot%\servicing\Packages*containers*.mum &gt;containers.txt<br>for /f %%i in (&#8216;findstr /i . containers.txt 2^&gt;nul&#8217;) do dism /online /norestart /add-package:&#8221;%SystemRoot%\servicing\Packages\%%i&#8221;<br>del containers.txt<br>Dism /online /enable-feature /featurename:Containers -All /LimitAccess /ALL<br>pause</p></blockquote>



<p>執行完之後重新開機應該就可以找到Hyper-V的功能了，不過到這裡為止，仍然無法安裝Docker。<br>或者是說，如果不是<a href="https://docs.docker.com/docker-for-windows/install-windows-home/">Windows 10 Home搭配Docker使用WSL2(Windows Subsystem for Linux, WSL)</a>，那麼就無法使用Docker。</p>



<p>再更精確一點的說法，就是<a href="https://docs.docker.com/docker-for-windows/install/">Docker需要Hyper-V與Container的功能</a>，如果是Windows Home安裝WSL2再加上Docker，那麼就是在WSL2裡面執行Container，跑的是Linux，如果只需要執行Linux的Container是OK的。</p>



<p>不過若是需要在Windows Container和Linux Container之間切換的話，Windows 10 Home版本一般來說是無法達成，而且Docker搭配WSL2跑Linux Container若是使用到Docker-Compose的話，可能還會有一點點問題…</p>



<p>所以為了在Windows 10 Home的版本正常執行Docker(Hyper-V都透過秘技安裝了，應該還有秘技可以讓Docker正常在Windows 10 Home版本安裝與執行吧！)，所以我繼續在網路上搜尋可能的秘技，想要解決在Windows 10 Home版本使用Docker的問題。</p>



<p>這次的秘技不需要再執行指令安裝什麼東西，需要的是執行regedit編輯Windows登錄檔，透過將「HKLM\Software\Microsoft\Windows NT\CurrentVersion」底下的EditionID從「Core」更改為「Professional」，改完之後不需要重新開機，就可以執行最新版本的Docker安裝檔。</p>



<figure class="wp-block-image size-large"><img data-recalc-dims="1" loading="lazy" decoding="async" width="963" height="680" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/05/7f9b43ce-changewindowseditionid_windowsregistry.png?resize=963%2C680&#038;ssl=1" alt="" class="wp-image-34" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/05/7f9b43ce-changewindowseditionid_windowsregistry.png?w=963&amp;ssl=1 963w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/05/7f9b43ce-changewindowseditionid_windowsregistry.png?resize=300%2C212&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/05/7f9b43ce-changewindowseditionid_windowsregistry.png?resize=768%2C542&amp;ssl=1 768w" sizes="auto, (max-width: 963px) 100vw, 963px" /><figcaption>將EditionID從「Core」更改為「Professional」，改完之後不需要重新開機，就可以執行最新版本的Docker安裝檔</figcaption></figure>



<p>上面的這個修改Windows登錄檔的位置要記下來，或者是寫成一個指令檔。<br>因為Windows過一段時間(不知多久)會自己將更改的值改回「Core」(如果你改完忘了改回來)，尤其是Windows Update完之後。</p>



<p>這會有什麼影響呢？</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img data-recalc-dims="1" loading="lazy" decoding="async" width="336" height="351" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/05/cdf1ffcb-dockerswitchcontainerneedtochangewindowsregistry.png?resize=336%2C351&#038;ssl=1" alt="" class="wp-image-35" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/05/cdf1ffcb-dockerswitchcontainerneedtochangewindowsregistry.png?w=336&amp;ssl=1 336w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2020/05/cdf1ffcb-dockerswitchcontainerneedtochangewindowsregistry.png?resize=287%2C300&amp;ssl=1 287w" sizes="auto, (max-width: 336px) 100vw, 336px" /><figcaption>EditionID為「Core」的情況下無法切換Container</figcaption></figure></div>



<p>會影響的就是Docker切換Windows Container與更新Docker版本，如果Docker發現新的版本，但是當你要執行更新安裝的時候發現有問題，可以試著將EditionID再改為「Professional」，之後應該就可以更新了。<br>註：要透過Docker結合WSL2執行Linux Container必須是切換到Linux Container模式才行。<br>(不過也可以選擇不要在Windows下操作Docker跑Linux Container，直接在WSL2裡面安裝獨立的Docker)參考來源：</p>



<p><span>參考來源</span></p>



<ul class="wp-block-list"><li><a href="https://forums.docker.com/t/installing-docker-on-windows-10-home/11722">Installing Docker on Windows 10 Home</a></li></ul>
<p>這篇文章 <a href="https://tech.uccu.website/windows10-home-install-hyperv-docker.html">Windows 10 Home家用版安裝Hyper-V與Docker</a> 最早出現於 <a href="https://tech.uccu.website">泰克哪裡去</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tech.uccu.website/windows10-home-install-hyperv-docker.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">30</post-id>	</item>
	</channel>
</rss>
