一文看懂-Docker容器化

1、Docker簡介前端

1.1 什麼是dockerjava

docker的英文意思是 碼頭工人,意思就是搬運東西的意思,其實這和docker的特色是同樣的,docker提供的就是一種容器化搬運東西(咱們的軟件、程序)的過程。docker本身原本是運行在操做系統上一個程序軟件,它會提供一個容器環境,使咱們的程序獨立地運行在容器中,因此說,官方給docker起的這個名字也真是應景。mysql

就連圖標也是這麼生動形象,富有詩意,讓人浮想聯翩。。。。(這是去幼兒園的車,尚未拐進大學城)linux

試想下邊這樣一個場景:當咱們把咱們的web網站作成分佈式的時候,咱們就要加服務器,而後在各個服務器配置web所須要的配置,好比:數據庫、web服務器、運行時啥,這樣的咱們的網站才能跑起來,可是每當咱們加服務器的時候,咱們都要再從新配置一下,很繁瑣,有了docker,咱們就能夠把咱們的網站和所須要的環境配置好,打成一個包(docker鏡像),而後在服務器上安裝docker,用docker拉取打包好的鏡像,直接run(容器)起來就好了,什麼都不用管了,很方便,更加的便於管理,鏡像中修改配置,從新更新,全部的容器就也能修改了,咱們的網站也就修改更新了,特別的方便。nginx

1.2 docker的特色git

docker的特色包含在它的口號中github

第一句,是「Build, Ship and Run」。(搭建、運輸、運行)web

第二句,「Build once,Run anywhere(一次搭建,處處運行)」。sql

看了上邊的場景,咱們能夠理解這兩句話了,如今哪一個軟件不是一次搭建、處處運行,真的都很差意思說,從最開始的java,到如今的各類跨平臺前端框架(Flutter、ReactNative、Ionic啥的)、小程序框架(Taro),這是解放開發人員減小開發成本提升開發效率的三連擊造福碼農的事情啊,各類應用層出不窮,叫咱們情何以堪、不堪回首、首當其衝、衝鋒陷陣啊,一不當心就暴露了個人文化。docker

1.3 docker和虛擬機

一說到docker,相信你們以前也瞭解過,那就必需要和虛擬機作一下比較,其實docker是和虛擬機是相似的東西,咱們應該知道虛擬機就是在咱們的操做系統上虛擬出來一個電腦,而後裏邊能夠安裝、運行各類各樣的軟件,和咱們真的電腦是差很少的,咱們能夠拿着這個虛擬好的電腦(實際上是一個文件)在按了虛擬機的其餘電腦上能夠直接運行,裏邊的東西就不用咱們來回安裝和配置了,也是很方便的。

docker其實提供的也是這麼一種的技術,只不過它比虛擬機效率更加的高,啓動快,佔用資源小等一系列的優勢,並且虛擬機比較笨重,這是由於虛擬機和docker來實現思想上有本質的區別,咱們能夠經過下邊的兩張圖能夠對比一下:

虛擬機的運做原理:是虛擬電腦的硬件資源,把硬件資源分配出來,而後虛擬出來多個操做系統,虛擬出來的是一個完整的電腦。

docker的運做原理:虛擬的軟件資源,把電腦中的網絡、存儲啥的分紅幾份虛擬成容器,咱們的軟件運行在容器中,每一個容易只佔用電腦的部分所須要的資源,並非一個完整的電腦。

大概就像上邊那麼理解吧,反正也不知道是對不對,可是看起來應該不錯。

因此,從運做原理上來看,docker更加的輕量級,虛擬機更加的笨重,docker啓動也十分的快,部署起來也方便,因此愈來愈多的人開始使用docker起來。

下邊是一張虛擬機和docker的對比,這裏要注意一下:可是docker自己並非容器,而是建立容器的工具;而虛擬機它就是虛擬機了。

2、docker中的核心概念

下面咱們來介紹使用docker的過程當中必需要掌握的概念,理解這些概念對docker的使用和學習是很是必要的。

2.1 鏡像(Image)

鏡像究竟是個什麼東西呢,不少人在學習docker的時候都是一頭霧水的,但是是歪果仁對鏡像情有獨鍾吧,好多東西都有鏡像的概念。好比咱們安裝系統的.iso文件,其實就是鏡像,這裏你就能夠把鏡像認爲是一種模板。咱們可使用docker根據這個模板建立容器來運行,其實更能夠理解爲鏡像是比如github上的倉庫同樣,咱們能夠克隆下來源代碼而後運行,運行起來的代碼能夠是一個網站、一個應用程序啥的,這就能夠叫作容器。說白了,鏡像就是一堆靜態的模板,運行起來的鏡像就是容器。鏡像通常須要咱們拉取下來,是隻讀的,這個咱們克隆github上的倉庫是同樣同樣的。

docker鏡像中有分層的概念,就是一個鏡像可能基於好幾個鏡像,好比一個web運行環境可能須要操做系統ubuntu、數據庫mysql、.net core runtime運行時,那咱們拉取的這個鏡像就會包好這好幾個鏡像,這就好像咱們前邊說的打包好的運行環境同樣,直接就拉下來一個小電腦同樣。

2.2 容器(Container)

當咱們拉取了一個鏡像,而後run一下,就會根據這個鏡像運行出來一個容器,運行的容器就好像咱們的應用程序同樣,能夠訪問能夠中止,咱們運用屢次run命令,就運行了不少不少容器,也能夠說是鏡像的實例。從這個角度來看,咱們能夠把鏡像看做是類,容器看做new出來的實例,也是很合適的。

2.3 倉庫(Repository)

存放鏡像的地方就是倉庫,就比如存放代碼的地方是github同樣,咱們就把github稱爲代碼的倉庫,github算是最大的倉庫。那麼存放docker鏡像的地方咱們叫作dockerhub,是docker的中央倉庫。其實已經有dockerhub這個網站了(https://hub.docker.com/),這就是 存放docker鏡像的官方倉庫,好多官方的也保存在這裏,保證了鏡像的安全性和可靠性,咱們能夠從上邊拉取一下鏡像來運行咱們的軟件。固然咱們也能夠製做好咱們本身鏡像推送上去,不過這些確定是要官方審覈的,防止有些人寫入一些惡意代碼。不過咱們能夠推到咱們本身的dockerhub上去,供咱們本身使用,這個就好咱們的github帳號同樣了,屬於私有鏡像了。

2.4 數據卷(Volumn)

實際上咱們的容器就好像是一個簡易版的操做系統,只不過系統中只安裝了咱們的程序運行所須要的環境,前邊說到咱們的容器是new出來的實例,既然是new出來的實例那就會銷燬,那若是銷燬了咱們的程序產生出的須要持久化的數據怎麼辦呢,容器運行的時候咱們能夠進容器去查看,容器一旦銷燬就什麼都沒有了。因此數據卷就是來解決這個問題的,是用來作數據持久化到咱們的宿主機上容器間的數據共享,簡單的說就是將宿主機的目錄映射到容器中的目錄,應用程序在容器中的目錄讀寫數據會同步到宿主機上,這樣容器產生的數據就能夠持久化了,好比咱們的數據庫容器,就能夠把數據存到咱們宿主機上的真實磁盤上了。

docker中基本的概念已經說了,下面咱們就能夠來使用docker了。

3、docker的安裝與使用

因爲docker的服務端只能運行在linux操做系統上,固然咱們學習也能夠用windows來安裝docker,可是比較麻煩,須要開啓一系列的配置,咱們仍是暫時在一臺裝有虛擬機的linux系統上來學習docker。這裏咱們以linux ubuntu 16.04 版原本學習。

3.1 docker的安裝

咱們先執行命令安裝docker

1. 執行 sudo apt-get update 更新軟件包

2. 執行 sudo apt-get -y install docker.io 安裝docker

3. 輸入 docker version 檢查docker是否安裝成功

若是有下面的輸出,說明docker安裝成功

3.2 docker的使用

docker --help 查看幫助信息,通常的軟件都會有這個命令,再也不多說。

docker version  查看docker的版本。

docker info 查看docker的基本信息,有多少個容器、鏡像什麼的。

docker images  查看本機上的全部鏡像。

  REPOSITORY:倉庫,也是鏡像名稱。

  TAG:標籤,也是版本號,鏡像會有不一樣的版本號。

  IMAGE ID:鏡像id,根據這個id咱們能夠區分不一樣的鏡像,也能夠對某個鏡像進行操做。

  CREATED:建立時間。

  SIZE:鏡像的大小。

當前個人機器上沒有一個鏡像,顯示以下:

docker pull <鏡像名稱>:[標籤名稱]:拉取鏡像,默認不寫標籤名稱拉取最新的鏡像。

咱們輸入docker pull hello-world 拉取最新的hello-world鏡像

docker run <鏡像名稱> :運行一個鏡像,這時候就變成一個容器了,至關於new 一個Image了。下邊咱們run hello-world 運行這個鏡像,輸出如下信息:

至此,咱們的docker的hello-world已經運行成功了,接下來咱們來啓動一個nginx服務器,來從外邊訪問咱們容器裏的nginx看看。

一樣咱們先拉取nginx鏡像 docker pull nginx,而後等待拉取完成,運行nginx容器,docker run -p 8080:80 nginx

而後咱們用自帶的瀏覽器來訪問8080端口,出現welcom to nginx 表示啓動成功。

docker的使用方法基本就是上邊這樣了,接下來咱們就能夠看一下詳細的參數。

3.3 docker的命令

3.3.1 鏡像命令:

docker images 查看本機的鏡像。

  REPOSITORY:倉庫,也是鏡像名稱。

  TAG:標籤,也是版本號,鏡像會有不一樣的版本號。

  IMAGE ID:鏡像id,根據這個id咱們能夠區分不一樣的鏡像,也能夠對某個鏡像進行操做。

  CREATED:建立時間。

  SIZE:鏡像的大小。

docker rmi 刪除本地的鏡像,加上一個參數-f表示強制刪除,由於有時候如有運行的相關容器的時候是不能刪除的,如:docker rmi -f nginx 強行中止容器並刪除鏡像,無論是否有佔用狀況。

docker search 根據鏡像名稱搜索遠程倉庫中的鏡像,能夠看一下查到全部相關名稱的鏡像,能夠選擇咱們要拉取哪一個鏡像,下邊是搜索nignx相關的鏡像,紅色部分ok 說明是官方鏡像。

docker pull <鏡像名稱>:[標籤名稱]:拉取鏡像,默認不寫標籤名稱拉取最新的鏡像。

docker push 推送鏡像,當咱們製做了咱們本身的鏡像時,咱們就能夠推送到咱們本身的docker hub上去。

3.3.2 容器命令

有了鏡像咱們就能夠new一個鏡像實例了,也就是咱們所說的容器。

docker run :基於某個鏡像運行一個容器,若是本地有這個鏡像就根據本地的鏡像建立,若是沒有,就去遠程拉取一個鏡像再建立,參數以下:

-d:啓動一個容器,後臺運行,不會佔用咱們當前的控制檯,通常都要加上,以前咱們啓動nginx沒有指定這個參數,就會佔用當前控制檯,會一直掛起,有了這個命令就不會佔用了。

-i:以交互模式運行容器,一般會和-t一塊兒來使用(-it)。

-t:爲容器也建立一個命令行窗口,是容器內容的命令行窗口,好比咱們拉取一個ubuntu的鏡像,咱們想要在這個操做系統鏡像裏邊執行一些命令,那就須要這個參數了。

-P:這個是大寫的P,指定宿主機的隨機端口映射到容器內部的端口。

-p:這個是小寫的p,指定某個具體端口映射到容器內部端口,好比前邊咱們用-p 8080:80,就是讓宿主機的8080端口映射到容器內的80端口,這樣咱們就能夠在外部用8080端口訪問咱們容器內部的nginx了(默認容器必須有一個外部的映射端口,否則訪問不了)。

-v:指定宿主機與容器內部的目錄映射,就是以前的數據卷所須要的參數,好實現數據的持久化和同步。

--name="mynginx":爲容器指定一個名稱,若是沒有指定,那就分配一個隨機名稱。

下面用參數重啓啓動咱們的nginx鏡像:docker run -itd -p 8848:80 --name="mynginx" nginx

docker ps 顯示正在運行的容器,加一個參數-a 能夠看到中止中的容器

docker stop 中止容器 。

docker kill 強制中止容器。

docker restart 重啓容器。

docker rm 刪除容器,刪除後容器就不在了,就不能重啓和中止了。

docker inspect 查看容器的詳細信息。

以上就是差很少咱們經常使用的命令,具體的其餘更多的功能咱們能夠查看官方文檔 https://docs.docker.com/get-started/

4、Dockerfile

上邊都是咱們拉取別人的鏡像,咱們實際上也能夠製做本身的專屬鏡像,根據咱們的須要,配置好咱們本身的鏡像來使用。Dockerfile就是用來構建咱們的鏡像的文件,在裏邊能夠寫一些命令來構建咱們的鏡像,構建好後發佈到docker hub就能夠供別人拉取使用了。

Dockerfile是一個沒有後綴名的文本文件,咱們經過寫入一些命令來實現鏡像的構建。下面咱們先來看看Dockerfile是怎樣來編寫的。下邊的命令標識形式<> 表明須要的參數,[ ] 是可選參數。

FROM:指定基礎鏡像,全部構建的鏡像都必須有一個基礎鏡像,且FROM命令必須是Dockerfile的第一個命令。

  FROM <image> [AS <name>]   指定從一個鏡像構建 AS 起一個新的鏡像名字。

  FROM <image>[:<tag>] [AS <name>]  指定鏡像的版本tag。

  例如:FROM mysql:5.0  AS database

MAINTAINER:鏡像維護人的信息。

  MAINTAINER  <name>

  例如:MAINTAINER  haha  lsdjfl@163.com

RUN:構建鏡像時要執行的命令。

  RUN <command>

  例如:RUN ["executable", "param1", "param2"]    RUN ["dotnet restore","*.csproj"]

ADD:將本地的文件添加複製到容器中去,壓縮包會解壓,能夠訪問網絡上的文件,會自動下載。

  ADD <src>  <dest>

  例如:ADD  *.csproj  /app       添加csproj文件到容器中的app目錄下。

COPY:功能和ADD同樣,可是隻是複製,不會解壓或者下載文件。

CMD:啓動容器後執行的命令,和RUN不同,RUN是在構建鏡像是要運行的命令。當使用docker run運行容器的時候,這個能夠在命令行被覆蓋。

  CMD ["executable", "param1", "param2"]

ENTRYPOINT:也是執行命令,和CMD同樣,只是這個命令不會被命令行覆蓋。

  ENTRYPOINT ["executable", "param1", "param2"]

  例如:ENTRYPOINT ["donnet", "myapp.dll"]

LABEL:爲鏡像添加元數據,key-value形式的。

  LABEL <key>=<value>  <key>=<value>  <key>=<value>  ....

  例如:LABEL version="1.0"  description="這是一個web應用"

ENV:設置環境變量,有些容器運行時會須要某些環境變量 好比:JAVA_HOME。

  ENV  <key>  <value>   一次設置一個環境變量。

  ENV  <key>=<value>  <key>=<value>  <key>=<value>  ....  設置多個環境變量。

  例如:ENV  JAVA_HOME  /usr/java1.8/

EXPOSE:暴露對外的端口。

  EXPOSE <port>

  例如:EXPOSE  80

  這裏指的是容器內部程序的端口,雖然會和宿主機的同樣,可是實際上是兩個端口,容器運行時,須要用-p  映射外部端口才能訪問到容器內的端口。

VOLUME:指定數據持久化的目錄,官方語言叫作掛載。

  VOLUME  /var/log  指定容器中須要被掛載的目錄,會把這個目錄映射到宿主機的一個隨機目錄上,實現數據的持久化和同步。

  VOLUME  ["/var/log","/var/test".....]  指定容器中多個須要被掛載的目錄,會把這些目錄映射到宿主機的多個隨機目錄上,實現數據的持久化和同步。

  VOLUME  /var/data  var/log   指定容器中的var/log目錄掛載到宿主機上的/var/data目錄,這種形式能夠手動指定宿主機上的目錄。

WORKDIR:設置工做目錄,設置完工做目錄以後 ,上邊的RUN、CMD、COPY、ADD等的工做目錄都變成這個了。

  WORKDIR <path>

  例如:WORKDIR  /app/test

USER:指定運行命令時所使用的用戶,爲了安全和權限起見,有的用戶可能權限高,有的用戶可能權限低,根據要執行的命令選擇不一樣的用戶。

  USER  <user>:[<group>]

  例如:USER  test

ARG:設置構建鏡像是要傳遞的參數。

  ARG  <name>[=<value>]

  例如:ARG  name=sss

以上是差很少構建Dockerfile時所使用的命令的,構建時命令是從上到下順序執行的,可能後邊的命令須要前邊命令的結果,使用 docker build 編譯Dockerfile 就能夠構建咱們的鏡像了。

docker build 可使用參數 -f 指定Dockerfile的目錄,默認是在當前目錄下找;-t 指定構建的鏡像的名稱和標籤,例如:docker build -f  ./aa/bb -t myimage:1.0

5、構建咱們本身的鏡像

有了上面的基礎,咱們就能夠構建咱們本身的鏡像了,而後還能夠上傳到咱們本身的docker hub上供別人拉取使用。接下里咱們就來實現如下。這裏參考了官方的構建步驟:https://docs.docker.com/engine/examples/dotnetcore/

5.1 建立一個mvc項目

首先找一個目錄,建立一個文件夾DockerDemo,而後在該目錄下執行命令dotnet new mvc,建立咱們的mvc程序,以下:

5.2 添加Dockerfile文件

咱們直接添加一個名稱爲Dockerfile的文件,而後輸入一下命令: 

#構建sdk鏡像,是爲了進行編譯、發佈咱們的web應用
FROM mcr.microsoft.com/dotnet/core/sdk:2.2 AS build-env
# 在容器中設置一個/app目錄
WORKDIR /app

# 複製csproj文件 到當前目錄下(app目錄下) 並執行dotnet restore 還原包
COPY *.csproj ./
RUN dotnet restore

# 再複製其餘剩餘的文件到當前目錄,執行發佈命令,用Release模式 而且輸出到out文件夾
COPY . ./
RUN dotnet publish -c Release -o out


#構建運行時鏡像
FROM mcr.microsoft.com/dotnet/core/aspnet:2.2
# 設置運行時鏡像一個/app目錄
WORKDIR /app
# 複製以前的鏡像的產物中的 /app/out目錄下的文件 到當前新鏡像的 /app錄下(當前目錄)
COPY --from=build-env /app/out .
# 執行dotnet 命令,運行咱們的web應用
ENTRYPOINT ["dotnet", "DockerDemo.dll"]

我用vscode添加Dockerfile直接變成了一個鯨魚的圖標,說明是一個Docker文件,還有高亮:

5.3 構建Docker鏡像

咱們直接把DockerDemo這個文件夾直接複製到虛擬機中,我複製到了Desktop下:

而後進入到DockerDemo目錄下,直接執行命令 docker build -t dockerdemo . ,這句命令的意思是 使用當前目錄下的Dockerfile構建鏡像dockerdemo,注意構建的鏡像名稱必須爲小寫,不然會報錯。

而後就是等待構建了,可能會比較慢, 若是想快的話,能夠換成國內的鏡像源,這裏就不說了,由於我也懶得換。

此次構建過程會分爲兩步,由於有兩個鏡像,構建完成後,咱們使用docker images 查看,會發現有咱們新構建的鏡像dockerdemo:

5.4 運行容器

接下來咱們輸入命令 docker run -d -p 8848:80 --name myapp dockerdemo,運行一個容器,名稱叫作myapp

 使用docker ps 查看運行中的容器:

5.5 訪問咱們的mvc程序

在虛擬機的瀏覽器中輸入 http://localhost:8848,或者在你的電腦上輸入虛擬機的地址來訪問 http://192.168.226.130:8848/ (這個是個人地址)顯示以下,表名成功:

 6、發佈鏡像

咱們已經構建好了咱們的鏡像,接下來咱們就把鏡像推送到咱們本身的docker倉庫中去,這一步和github是徹底同樣的,就像把咱們的代碼推送到github上同樣。

6.1 建立帳號

首先,咱們須要建立一個dockerhub帳號,登陸https://hub.docker.com/,根據提示註冊帳號,這一步就不細說了。

6.2 登陸

命令行輸入docker login,輸入咱們的帳號密碼,進行登陸。

6.3 推送鏡像

推送鏡像以前,首先要標記咱們的鏡像,也就是給咱們的鏡像起一個名字,使用命令 docker tag <image> <username>/<repository>:<tag>,下邊咱們就標記咱們剛纔的dockerdemo的鏡像:

使用命令 docker tag dockerdemo emmaccc/dockerdemo:1.0.0

查看咱們剛纔標記過的鏡像:

使用命令 docker push emmaccc/dockerdemo:1.0.0  推送鏡像,等待一段時間後推送成功,就能夠在本身dockerhub帳號上看見了

6.4 使用鏡像

推送成功以後,咱們就能夠在任意一臺安裝了docker的計算機上來拉取咱們鏡像,直接run啓動咱們的web應用了。

docker run -p 4396:80 emmaccc/dockerdemo:1.0.0,運行以後,無需擔憂各類依賴、配置,也不用在你的新主機上安裝任何東西,直接run運行就好了,這也docker獨特的魅力所在。

6、總結

學習docker,前先後後看了好幾遍,到底是個什麼玩意啊,好半天才看懂,docker的基本使用就差很少了,接下來估計又是k8s了,唉,東西真多,感受全it界都在造輪子吧,非要搞這個搞那個,沒辦法,仍是得跟着大佬們走,若是你真的還不明白,那就送你一句話。

web放tomcat裏,tomcat放docker裏,docker放k8s裏,k8s放操做系統上,繞了一大圈,扯淡呢,咋不直接web放操做系統上直接運行呢。

 

相關文章
相關標籤/搜索