在計算機技術突飛猛進的今天, Docker 在國內發展的如火如荼,特別是在一線互聯網公司, Docker 的使用是十分廣泛的。
編寫此套教程,來帶你們去了解並熟練運用 docker ,祝願各位讀者朋友們學完此套教程後,在將來企業面試中可以多一項加分的籌碼,可以幫助到你們,我以爲就很值了。html
既然說了這麼多, docker 究竟是個什麼東西呢?python
咱們在理解 docker 以前,首先咱們得先區分清楚兩個概念,容器和虛擬機。linux
可能不少讀者朋友都用過虛擬機,而對容器這個概念比較的陌生。nginx
咱們用的傳統虛擬機如 VMware , VisualBox 之類的須要模擬整臺機器包括硬件,每臺虛擬機都須要有本身的操做系統,虛擬機一旦被開啓,預分配給它的資源將所有被佔用。每一臺虛擬機包括應用,必要的二進制和庫,以及一個完整的用戶操做系統。git
而容器技術是和咱們的宿主機共享硬件資源及操做系統,能夠實現資源的動態分配。容器包含應用和其全部的依賴包,可是與其餘容器共享內核。容器在宿主機操做系統中,佔用用戶空間以分離的進程運行。github
容器技術是實現操做系統虛擬化的一種途徑,可讓您在資源受到隔離的進程中運行應用程序及其依賴關係。經過使用容器,咱們能夠輕鬆打包應用程序的代碼、配置和依賴關係,將其變成容易使用的構建塊,從而實現環境一致性、運營效率、開發人員生產力和版本控制等諸多目標。容器能夠幫助保證應用程序快速、可靠、一致地部署,其間不受部署環境的影響。容器還賦予咱們對資源更多的精細化控制能力,讓咱們的基礎設施效率更高。經過下面這幅圖咱們能夠很直觀的反映出這二者的區別所在web
Docker 屬於 Linux 容器的一種封裝,提供簡單易用的容器使用接口。
它是目前最流行的 Linux 容器解決方案。面試
而 Linux 容器是 Linux 發展出了另外一種虛擬化技術,簡單來說, Linux 容器不是模擬一個完整的操做系統,而是對進程進行隔離,至關因而在正常進程的外面套了一個保護層。對於容器裏面的進程來講,它接觸到的各類資源都是虛擬的,從而實現與底層系統的隔離。sql
Docker 將應用程序與該程序的依賴,打包在一個文件裏面。運行這個文件,就會生成一個虛擬容器。程序在這個虛擬容器裏運行,就好像在真實的物理機上運行同樣。有了 Docker ,就不用擔憂環境問題。docker
整體來講, Docker 的接口至關簡單,用戶能夠方便地建立和使用容器,把本身的應用放入容器。容器還能夠進行版本管理、複製、分享、修改,就像管理普通的代碼同樣。
Docker相比於傳統虛擬化方式具備更多的優點:
從上圖咱們能夠看到,Docker 中包括三個基本的概念:
鏡像是 Docker 運行容器的前提,倉庫是存放鏡像的場所,可見鏡像更是 Docker 的核心。
那麼鏡像究竟是什麼呢?
Docker 鏡像能夠看做是一個特殊的文件系統,除了提供容器運行時所需的程序、庫、資源、配置等文件外,還包含了一些爲運行時準備的一些配置參數(如匿名卷、環境變量、用戶等)。鏡像不包含任何動態數據,其內容在構建以後也不會被改變。
鏡像(Image)就是一堆只讀層(read-only layer)的統一視角,也許這個定義有些難以理解,下面的這張圖可以幫助讀者理解鏡像的定義。
從左邊咱們看到了多個只讀層,它們重疊在一塊兒。除了最下面一層,其它層都會有一個指針指向下一層。這些層是Docker 內部的實現細節,而且可以在主機的文件系統上訪問到。統一文件系統 (union file system) 技術可以將不一樣的層整合成一個文件系統,爲這些層提供了一個統一的視角,這樣就隱藏了多層的存在,在用戶的角度看來,只存在一個文件系統。咱們能夠在圖片的右邊看到這個視角的形式。
容器 (container) 的定義和鏡像 (image) 幾乎如出一轍,也是一堆層的統一視角,惟一區別在於容器的最上面那一層是可讀可寫的。
因爲容器的定義並無說起是否要運行容器,因此實際上,容器 = 鏡像 + 讀寫層。
Docker 倉庫是集中存放鏡像文件的場所。鏡像構建完成後,能夠很容易的在當前宿主上運行,可是, 若是須要在其它服務器上使用這個鏡像,咱們就須要一個集中的存儲、分發鏡像的服務,Docker Registry (倉庫註冊服務器)就是這樣的服務。有時候會把倉庫 (Repository) 和倉庫註冊服務器 (Registry) 混爲一談,並不嚴格區分。Docker 倉庫的概念跟 Git 相似,註冊服務器能夠理解爲 GitHub 這樣的託管服務。實際上,一個 Docker Registry 中能夠包含多個倉庫 (Repository) ,每一個倉庫能夠包含多個標籤 (Tag),每一個標籤對應着一個鏡像。因此說,鏡像倉庫是 Docker 用來集中存放鏡像文件的地方相似於咱們以前經常使用的代碼倉庫。
一般,一個倉庫會包含同一個軟件不一樣版本的鏡像,而標籤就經常使用於對應該軟件的各個版本 。咱們能夠經過 <倉庫名> : <標籤> 的格式來指定具體是這個軟件哪一個版本的鏡像。若是不給出標籤,將以 latest 做爲默認標籤.。
倉庫又能夠分爲兩種形式:
Docker Registry 公有倉庫是開放給用戶使用、容許用戶管理鏡像的 Registry 服務。通常這類公開服務容許用戶免費上傳、下載公開的鏡像,並可能提供收費服務供用戶管理私有鏡像。
除了使用公開服務外,用戶還能夠在本地搭建私有 Docker Registry 。Docker 官方提供了 Docker Registry 鏡像,能夠直接使用作爲私有 Registry 服務。當用戶建立了本身的鏡像以後就可使用 push 命令將它上傳到公有或者私有倉庫,這樣下次在另一臺機器上使用這個鏡像時候,只須要從倉庫上 pull 下來就能夠了。
咱們主要把 Docker 的一些常見概念如 Image , Container , Repository 作了詳細的闡述,也從傳統虛擬化方式的角度闡述了 docker 的優點,咱們從下圖能夠直觀地看到 Docker 的架構:
Docker 使用 C/S 結構,即客戶端/服務器體系結構。 Docker 客戶端與 Docker 服務器進行交互,Docker服務端負責構建、運行和分發 Docker 鏡像。 Docker 客戶端和服務端能夠運行在一臺機器上,也能夠經過 RESTful 、 stock 或網絡接口與遠程 Docker 服務端進行通訊。
Docker 的安裝和使用有一些前提條件,主要體如今體系架構和內核的支持上。對於體系架構,除了 Docker 一開始就支持的 X86-64 ,其餘體系架構的支持則一直在不斷地完善和推動中。
Docker 分爲 CE 和 EE 兩大版本。 CE 即社區版(免費,支持週期 7 個月), EE 即企業版,強調安全,付費使用,支持週期 24 個月。
咱們在安裝前能夠參看官方文檔獲取最新的 Docker 支持狀況,官方文檔在這裏
https://docs.docker.com/install/
Docker 對於內核支持的功能,即內核的配置選項也有必定的要求(好比必須開啓 Cgroup 和 Namespace 相關選項,以及其餘的網絡和存儲驅動等), Docker 源碼中提供了一個檢測腳原本檢測和指導內核的配置,腳本連接在這裏:
https://raw.githubusercontent.com/docker/docker/master/contrib/check-config.sh
在知足前提條件後,安裝就變得很是的簡單了。
Docker CE 的安裝請參考官方文檔:
這裏咱們以 CentOS7 做爲本文的演示。
阿里雲服務器(1核2G,1M帶寬)
CentOS 7.4 64位
因爲 Docker-CE 支持 64 位版本的 CentOS7 ,而且要求內核版本不低於 3.10
首先咱們須要卸載掉舊版本的 Docker,若是你以前未安裝過,能夠跳過此步驟
$ sudo yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-selinux \ docker-engine-selinux \ docker-engine
$ sudo yum install -y yum-utils \ device-mapper-persistent-data \ lvm2
Docker 軟件包已經包括在默認的 CentOS-Extras 軟件源裏。所以想要安裝 docker,只須要運行下面的 yum 命令
$ sudo yum install docker
固然在測試或開發環境中 Docker 官方爲了簡化安裝流程,提供了一套便捷的安裝腳本,CentOS 系統上可使用這套腳本安裝:
curl -fsSL get.docker.com -o get-docker.sh
sh get-docker.sh
具體能夠參看 docker-install 的腳本:
https://github.com/docker/docker-install
執行這個命令後,腳本就會自動的將一切準備工做作好,而且把 Docker CE 的 Edge 版本安裝在系統中。
安裝過程當中可能會出現這個問題,Delta RPMs disabled because /usr/bin/applydeltarpm not installed.
這時應該是咱們服務器還確實依賴包,執行一下命令安裝
yum provides '*/applydeltarpm'
yum install deltarpm
而後從新執行
curl -fsSL get.docker.com -o get-docker.sh
sh get-docker.sh
安裝過程鍾可能出現另外一個問題,No Presto metadata available for docker-ce-edge No Presto metadata available for base
在網上查到緣由:因爲國內訪問不到docker官方鏡像的緣故
能夠經過aliyun的源來完成,作以下操做問題解決:yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
而後從新執行
curl -fsSL get.docker.com -o get-docker.sh
sh get-docker.sh
安裝完成後,運行下面的命令,驗證是否安裝成功:
docker version or docker info
$ sudo systemctl enable docker
$ sudo systemctl start docker
咱們經過最簡單的 image 文件 hello world,感覺一下 Docker 的魅力吧!
咱們直接運行下面的命令,將名爲 hello-world 的 image 文件從倉庫抓取到本地。
docker pull library/hello-world
docker pull images 是抓取 image 文件, library/hello-world 是 image 文件在倉庫裏面的位置,其中 library 是 image 文件所在的組, hello-world 是 image 文件的名字。
抓取成功之後,就能夠在本機看到這個 image 文件了。
docker images
咱們能夠看到以下結果:
如今,咱們能夠運行 hello-world 這個 image 文件
docker run hello-world
輸出這段提示之後,hello world 就會中止運行,容器自動終止。有些容器不會自動終止,由於提供的是服務,好比Mysql鏡像等。
是否是很容易呢?咱們從上面能夠看出, docker 的功能是十分強大的,除此以外,咱們還能夠拉去一些 Ubuntu , Apache 等鏡像。
Docker 提供了一套簡單實用的命令來建立和更新鏡像,咱們能夠經過網絡直接下載一個已經建立好了的應用鏡像,並經過 Docker RUN 命令就能夠直接使用。當鏡像經過 RUN 命令運行成功後,這個運行的鏡像就是一個 Docker 容器啦,容器能夠理解爲一個輕量級的沙箱, Docker 利用容器來運行和隔離應用,容器是能夠被啓動、中止、刪除的,這並不會影響 Docker 鏡像。
咱們能夠看看下面這幅圖:
Docker 客戶端是 Docker 用戶與 Docker 交互的主要方式。當您使用 docker 命令行運行命令時, Docker 客戶端將這些命令發送給服務器端,服務端將執行這些命令。 docker 命令使用 docker API 。 Docker 客戶端能夠與多個服務端進行通訊。
咱們將剖析一下 Docker 容器是如何工做的,學習好Docker容器工做的原理,咱們就能夠本身去管理咱們的容器了。
在上面的學習中,咱們簡單地講解了Docker的基本架構。瞭解到了Docker 使用的是 C/S 結構,即客戶端/服務器體系結構。明白了 Docker 客戶端與 Docker 服務器進行交互時, Docker 服務端負責構建、運行和分發 Docker 鏡像。 也知道了Docker 客戶端和服務端能夠運行在一臺機器上,能夠經過 RESTful 、 stock 或網絡接口與遠程 Docker 服務端進行通訊。
咱們從下圖能夠很直觀的瞭解到Docker的架構:
Docker 的核心組件包括:
Docker 採用的是 Client/Server 架構。客戶端向服務器發送請求,服務器負責構建、運行和分發容器。客戶端和服務器能夠運行在同一個 Host 上,客戶端也能夠經過 socket 或 REST API 與遠程的服務器通訊。
Docker Client ,也稱 Docker 客戶端。它其實就是 Docker 提供命令行界面 (CLI) 工具,是許多 Docker 用戶與 Docker 進行交互的主要方式。客戶端能夠構建,運行和中止應用程序,還能夠遠程與Docker_Host進行交互。最經常使用的 Docker 客戶端就是 docker 命令,咱們能夠經過 docker 命令很方便地在 host 上構建和運行 docker 容器。
Docker daemon 是服務器組件,以 Linux 後臺服務的方式運行,是 Docker 最核心的後臺進程,咱們也把它稱爲守護進程。它負責響應來自 Docker Client 的請求,而後將這些請求翻譯成系統調用完成容器管理操做。該進程會在後臺啓動一個 API Server ,負責接收由 Docker Client 發送的請求,接收到的請求將經過Docker daemon 內部的一個路由分發調度,由具體的函數來執行請求。
咱們大體能夠將其分爲如下三部分:
Docker Daemon的架構以下所示:
Docker Daemon 能夠認爲是經過 Docker Server 模塊接受 Docker Client 的請求,並在 Engine 中處理請求,而後根據請求類型,建立出指定的 Job 並運行。 Docker Daemon 運行在 Docker host 上,負責建立、運行、監控容器,構建、存儲鏡像。
運行過程的做用有如下幾種可能:
啓動 Docker Daemon 時,通常可使用如下命令來完成
docker --daemon = true docker –d docker –d = true
再由 docker 的 main() 函數來解析以上命令的相應 flag 參數,並最終完成 Docker Daemon 的啓動。
下圖能夠很直觀地看到 Docker Daemon 的啓動流程:
默認配置下, Docker daemon 只能響應來自本地 Host 的客戶端請求。若是要容許遠程客戶端請求,須要在配置文件中打開 TCP 監聽。咱們能夠照着以下步驟進行配置:
systemctl daemon-reload
systemctl restart docker.service
docker -H 服務器IP地址 info
-H 是用來指定服務器主機, info 子命令用於查看 Docker 服務器的信息
Docker 鏡像能夠看做是一個特殊的文件系統,除了提供容器運行時所需的程序、庫、資源、配置等文件外,還包含了一些爲運行時準備的一些配置參數(如匿名卷、環境變量、用戶等)。鏡像不包含任何動態數據,其內容在構建以後也不會被改變。咱們可將 Docker 鏡像當作只讀模板,經過它能夠建立 Docker 容器。
鏡像有多種生成方法:
咱們能夠將鏡像的內容和建立步驟描述在一個文本文件中,這個文件被稱做 Dockerfile ,經過執行 docker build
Docker registry 是存儲 docker image 的倉庫,它在 docker 生態環境中的位置以下圖所示:
運行docker push、docker pull、docker search時,其實是經過 docker daemon 與 docker registry 通訊。
Docker 容器就是 Docker 鏡像的運行實例,是真正運行項目程序、消耗系統資源、提供服務的地方。 Docker Container 提供了系統硬件環境,咱們可使用 Docker Images 這些製做好的系統盤,再加上咱們所編寫好的項目代碼, run 一下就能夠提供服務啦。
看到這裏,我相信各位讀者朋友們應該已經對Docker基礎架構已經熟悉的差很少了,咱們還記得運行的第一個容器嗎?如今咱們再經過hello-world這個例子來體會一下 Docker 各個組件是如何協做的。
容器啓動過程以下:
Docker 客戶端執行 docker run 命令
Docker daemon 發現本地沒有 hello-world 鏡像
daemon 從 Docker Hub 下載鏡像
下載完成,鏡像 hello-world 被保存到本地
Docker daemon 啓動容器
具體過程能夠看以下這幅演示圖:
咱們能夠經過docker images 能夠查看到 hello-world 已經下載到本地。
咱們能夠經過docker ps 或者 docker container ls 顯示正在運行的容器,咱們能夠看到, hello-world 在輸出提示信息之後就會中止運行,容器自動終止,因此咱們在查看的時候沒有發現有容器在運行。
咱們把 Docker 容器的工做流程剖析的十分清楚了,咱們大致能夠知道 Docker 組件協做運行容器能夠分爲如下幾個過程:
瞭解了這些過程之後,咱們再來理解這些命令就不會以爲很突兀了,下面咱們看一下 Docker 經常使用的一些命令操做吧。
咱們能夠經過 docker -h 去查看命令的詳細的幫助文檔。在這裏我只會講一些日常平常比賽或者生活中咱們可能會用的比較多的一些命令
例如,咱們須要拉取一個 docker 鏡像,咱們能夠用以下命令:
docker pull image_name
image_name 爲鏡像的名稱,而若是咱們想從 Docker Hub 上去下載某個鏡像,咱們可使用如下命令:
docker pull centos:latest
centos:lastest 是鏡像的名稱, Docker daemon 發現本地沒有咱們須要的鏡像,會自動去 Docker Hub 上去下載鏡像,下載完成後,該鏡像被默認保存到 /var/lib/docker 目錄下。
接着咱們若是想查看下主機下存在多少鏡像,咱們能夠用以下命令:
docker images
咱們要想知道當前有哪些容器在運行,咱們能夠用以下命令:
docker ps -a
-a 是查看當前全部的容器,包括未運行的
咱們該如何去對一個容器進行啓動,重啓和中止呢?咱們能夠用以下命令:
docker start container_name/container_id docker restart container_name/container_id docker stop container_name/container_id
這個時候咱們若是想進入到這個容器中,咱們可使用 attach 命令:
docker attach container_name/container_id
那若是咱們想運行這個容器中的鏡像的話,而且調用鏡像裏面的 bash ,咱們可使用以下命令:
cdocker run -t -i container_name/container_id /bin/bash
那若是這個時候,咱們想刪除指定鏡像的話,因爲 image 被某個 container 引用(拿來運行),若是不將這個引用的 container 銷燬(刪除),那 image 確定是不能被刪除。咱們首先得先去中止這個容器:
docker ps
docker stop container_name/container_id
而後咱們用以下命令去刪除這個容器:
docker rm container_name/container_id
而後這個時候咱們再去刪除這個鏡像:
docker rmi image_name
此時,經常使用的 Docker 相關的命令就講到這裏爲止了。
前面咱們已經提到了 Docker 的一些基本概念。咱們能夠去使用 Dockerfile 定義鏡像,依賴鏡像來運行容器,能夠去模擬出一個真實的漏洞場景。所以毫無疑問的說, Dockerfile 是鏡像和容器的關鍵,而且 Dockerfile 還能夠很輕易的去定義鏡像內容,說了這麼多,那麼 Dockerfile 究竟是個什麼東西呢?
Dockerfile 是自動構建 docker 鏡像的配置文件, 用戶可使用 Dockerfile 快速建立自定義的鏡像。Dockerfile 中的命令很是相似於 linux 下的 shell 命令。
咱們能夠經過下面這幅圖來直觀地感覺下 Docker 鏡像、容器和 Dockerfile 三者之間的關係。
咱們從上圖中能夠看到, Dockerfile 能夠自定義鏡像,經過 Docker 命令去運行鏡像,從而達到啓動容器的目的。
Dockerfile 是由一行行命令語句組成,而且支持已 # 開頭的註釋行。
通常來講,咱們能夠將 Dockerfile 分爲四個部分:
下面是一段簡單的Dockerfile的例子(也能夠看下文的asp.net core 的dockerfile配置文件):
FROM python:2.7 MAINTAINER Angel_Kitty <angelkitty6698@gmail.com> COPY . /app WORKDIR /app RUN pip install -r requirements.txt EXPOSE 5000 ENTRYPOINT ["python"] CMD ["app.py"]
咱們能夠分析一下上面這個過程:
這個例子是啓動一個 python flask app 的 Dockerfile ( flask 是 python 的一個輕量的 web 框架),相信你們從這個例子中可以稍微理解了Dockfile的組成以及指令的編寫過程。
根據上面的例子,咱們已經差很少知道了Dockerfile的組成以及指令的編寫過程,咱們再來理解一下這些經常使用命令就會駕輕就熟了。
因爲 Dockerfile 中全部的命令都是如下格式:INSTRUCTION argument ,指令 (INSTRUCTION) 不分大小寫,可是推薦大寫。
FROM
FROM 是用於指定基礎的 images ,通常格式爲 FROM or FORM :,全部的 Dockerfile 都用該以 FROM 開頭,FROM 命令指明 Dockerfile 所建立的鏡像文件以什麼鏡像爲基礎,FROM 之後的全部指令都會在 FROM 的基礎上進行建立鏡像。能夠在同一個 Dockerfile 中屢次使用 FROM 命令用於建立多個鏡像。好比咱們要指定 python 2.7 的基礎鏡像,咱們能夠像以下寫法同樣:
FROM python:2.7
MAINTAINER
MAINTAINER 是用於指定鏡像建立者和聯繫方式,通常格式爲 MAINTAINER
MAINTAINER Angel_Kitty XXX@gmail.com
COPY
COPY 是用於複製本地主機的
當使用本地目錄爲源目錄時,推薦使用 COPY 。通常格式爲 COPY
COPY . /app
WORKDIR
WORKDIR 用於配合 RUN,CMD,ENTRYPOINT 命令設置當前工做路徑。能夠設置屢次,若是是相對路徑,則相對前一個 WORKDIR 命令。默認路徑爲/。通常格式爲 WORKDIR /path/to/work/dir 。例如咱們設置/app 路徑,咱們能夠進行以下操做:
WORKDIR /app
RUN
RUN 用於容器內部執行命令。每一個 RUN 命令至關於在原有的鏡像基礎上添加了一個改動層,原有的鏡像不會有變化。通常格式爲 RUN
RUN pip install -r requirements.txt
EXPOSE
EXPOSE 命令用來指定對外開放的端口。通常格式爲 EXPOSE
例如上面那個例子,開放5000端口:
EXPOSE 5000
ENTRYPOINT
ENTRYPOINT 可讓你的容器表現得像一個可執行程序同樣。一個 Dockerfile 中只能有一個 ENTRYPOINT,若是有多個,則最後一個生效。
ENTRYPOINT 命令也有兩種格式:
ENTRYPOINT ["executable", "param1", "param2"] :推薦使用的 exec形式
ENTRYPOINT command param1 param2 :shell 形式
例以下面這個,咱們要將 python 鏡像變成可執行的程序,咱們能夠這樣去作:
ENTRYPOINT ["python"]
CMD
CMD 命令用於啓動容器時默認執行的命令,CMD 命令能夠包含可執行文件,也能夠不包含可執行文件。不包含可執行文件的狀況下就要用 ENTRYPOINT 指定一個,而後 CMD 命令的參數就會做爲ENTRYPOINT的參數。
CMD 命令有三種格式:
CMD ["executable","param1","param2"]:推薦使用的 exec 形式。
CMD ["param1","param2"]:無可執行程序形式
CMD command param1 param2:shell 形式。
一個 Dockerfile 中只能有一個CMD,若是有多個,則最後一個生效。而 CMD 的 shell 形式默認調用 /bin/sh -c 執行命令。
CMD 命令會被 Docker 命令行傳入的參數覆蓋:docker run busybox /bin/echo Hello Docker 會把 CMD 裏的命令覆蓋。
例如咱們要啓動 /app ,咱們能夠用以下命令實現:
CMD ["app.py"]
固然還有一些其餘的命令,咱們在用到的時候再去一一講解一下。
咱們大致已經把Dockerfile的寫法講述完畢,咱們能夠本身動手寫一個例子:
mkdir static_web cd static_web touch Dockerfile 而後 vi Dockerfile 開始編輯該文件 輸入 i 開始編輯 如下是咱們構建的Dockerfile內容 FROM nginx MAINTAINER Angel_Kitty <XXX@gmail.com> RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html 編輯完後 按 esc 退出編輯 而後 :wq 寫入 退出
咱們在 Dockerfile 文件所在目錄執行:
docker build -t angelkitty/nginx_web:v1 .
這個命令就是建立一個docker鏡像()
咱們解釋一下, -t 是爲新鏡像設置倉庫和名稱,其中 angelkitty 爲倉庫名, nginx_web 爲鏡像名, :v1 爲標籤(不添加爲默認 latest )
咱們構建完成以後,使用 docker images 命令查看全部鏡像,若是存在 REPOSITORY 爲 nginx 和 TAG 是 v1 的信息,就表示構建成功
接下來使用 docker run 命令來啓動容器
docker run --name nginx_web -d -p 8080:80 angelkitty/nginx_web:v1
如圖,證實咱們建立的docker服務正在運行。
這條命令會用 nginx 鏡像啓動一個容器,命名爲 nginx_web ,而且映射了 8080 端口,這樣咱們能夠用瀏覽器去訪問這個 nginx 服務器:http://localhost:8080/ 或者 http://本機的IP地址:8080/,因爲這裏我是在服務器啓動的,nginx沒有作反代,這裏就不演示了訪問後的效果了。
這樣一個簡單使用 Dockerfile 構建鏡像,運行容器的示例就完成了!
下文會詳細介紹asp.net core 配置docker鏡像,而後服務器實戰docker部署並做nginx反代。
在這裏咱們拋出幾個問題:
asp.net core 作成鏡像並部署是一個什麼樣的流程
開發環境和服務器不一致會不會有影響,eg:咱們用window開發,項目實際是部署在Linux上
用於開發和生成 .NET Core 應用的映像(microsoft/dotnet:2.1-sdk),.NET Core,包含 SDK,適用於 Linux 和 Windows(多體系結構)
用於運行 .NET Core 應用的映像(microsoft/dotnet:2.1-aspnetcore-runtime),ASP.NET Core,包含僅運行時和 ASP.NET Core 優化,適用於 Linux 和 Windows(多體系結構)
爲何是多個映像? 由於在開發、生成和運行容器化應用程序時,一般具備不一樣的優先級。 經過爲這些單獨的任務提供不一樣的映像,Microsoft 有助於優化開發、生成和部署應用程序的單獨進程
在開發期間,重要的是可循環訪問更改的速度以及調試更改的能力。 與更改代碼的能力和快速查看更改相比,映像的大小不是那麼重要。
在生產中重要的是基於生產 .NET Core 映像部署和啓動容器的速度。 所以,基於 microsoft/dotnet:2.1-aspnetcore-runtime 的僅運行時鏡像很小,以便它能夠經過網絡從 Docker 註冊表快速傳輸到 Docker 主機,在生產鏡像中,只放置運行應用程序所需的二進制文件和其餘內容
接下來經過實戰項目,詳細的給你們介紹一下asp.net core在docker中的部署
dotnet new mvc -o website cd website ls ... dotnet dev-certs https --trust dotnet watch run
建立mvc項目到website 文件夾下,cd 進入文件夾 dotnet watch run 先本地運行一下項目,若是沒有問題下面建立Dockerfile文件
這裏咱們用的是.net core 2.2 sdk
FROM microsoft/dotnet:2.2-sdk AS build WORKDIR /app # copy csproj and restore as distinct layers # COPY *.sln . COPY *.csproj ./ RUN dotnet restore # copy everything else and build app COPY . ./ WORKDIR /app RUN dotnet publish -c Release -o out FROM microsoft/dotnet:2.2-aspnetcore-runtime AS runtime WORKDIR /app COPY --from=build /app/out ./ ENTRYPOINT ["dotnet", "website.dll"]
這裏咱們能夠避免開發環境的bin和obj與容器中bin和obj的衝突
<Project> <PropertyGroup> <DefaultItemExcludes>$(DefaultItemExcludes);$(MSBuildProjectDirectory)/obj/**/*</DefaultItemExcludes> <DefaultItemExcludes>$(DefaultItemExcludes);$(MSBuildProjectDirectory)/bin/**/*</DefaultItemExcludes> </PropertyGroup> <PropertyGroup Condition="'$(DOTNET_RUNNING_IN_CONTAINER)' == 'true'"> <BaseIntermediateOutputPath>$(MSBuildProjectDirectory)/obj/container/</BaseIntermediateOutputPath> <BaseOutputPath>$(MSBuildProjectDirectory)/bin/container/</BaseOutputPath> </PropertyGroup> <PropertyGroup Condition="'$(DOTNET_RUNNING_IN_CONTAINER)' != 'true'"> <BaseIntermediateOutputPath>$(MSBuildProjectDirectory)/obj/local/</BaseIntermediateOutputPath> <BaseOutputPath>$(MSBuildProjectDirectory)/bin/local/</BaseOutputPath> </PropertyGroup> </Project>
docker build --pull -t dongshengpro/websiteimage:1.0 .
docker build --pull -t websiteimage:1.0 .
docker run --name websiteimage:1.0 --rm -it -p 8090:80 websiteimage:1.0
docker run --name websiteimage:1.0 -d -p 8090:80 websiteimage:1.0
-d 會直接將容器作成服務
在win上的時候,有時候,咱們運行docker 容器,可能須要經過查看一下docker 容器ip
docker exec 鏡像明 ipconfig
Windows using Linux containers
docker run --rm -it -p 8000:80 -v c:\git\dotnet-docker\samples\aspnetapp:/app/ -w /app/aspnetapp microsoft/dotnet:2.2-sdk dotnet watch run
You can use CTRL-C to terminate dotnet watch
. Navigate to the site at http://localhost:8000
in your browser.
macOS or Linux using Linux containers
docker run --rm -it -p 8000:80 -v ~/git/dotnet-docker/samples/aspnetapp:/app/ -w /app/aspnetapp microsoft/dotnet:2.2-sdk dotnet watch run
You can use CTRL-C to terminate dotnet watch
. Navigate to the site at http://localhost:8000
in your browser.
Windows using Windows containers
docker run --rm -it -p 8000:80 -v c:\git\dotnet-docker\samples\aspnetapp:c:\app\ -w \app\aspnetapp --name aspnetappsample microsoft/dotnet:2.2-sdk dotnet watch run