docker入門(利用docker部署web應用)

前言:本課程是在慕課網上學習 第一個docker化的java應用 課程時所做的筆記,供本人複習之用

目錄

第一章 什麼是docker

1.1 docker的發展史

1.2 docker國內應用史

1.3 什麼是Docker

第二章 瞭解docker

2.1 docker思想

2.1.1 集裝箱

2.1.2 標準化

2.1.3 隔離

2.2 docker解決的問題

2.2.1 系統環境不一致

2.2.2 系統好卡,哪個哥們又寫死循環了

2.2.3 雙11來了,服務器撐不住了

第三章 走進docker

3.1 鏡像

3.2 容器

3.3 倉庫

第四章 centos下docker安裝

第五章 docker初體驗

5.1 docker基本命令

5.2 docker運行鏡像流程

第六章 docker運行nginx

6.1 運行nginx鏡像

6.2 docker網絡

6.2.1 網絡介紹

6.2.2 實際訪問端口

第七章 docker部署第一個java web應用

7.1 製作自己的鏡像

7.2 運行自己的鏡像


第一章 什麼是docker

1.1 docker的發展史

2010年幾個年輕人成立了一個做PAAS平臺的公司dotCloud.起初公司發展的不錯,不但拿到過一些融資,還獲得了美國著名孵化器YCombinator的支持,後來微軟谷歌亞馬遜這樣的大廠商也紛紛加入PAAS平臺,競爭十分激烈,dotCloud舉步維艱.

2013年可能是公司發展的不是很好,工程師又不想自己的努力付之東流,於是他們決定將他們的核心技術開源.這項技術就是docker.當時docker的功能就是將linux容器中的應用代碼打包,可以輕鬆的在服務器之間進行遷移.

無心插柳柳成蔭,docker技術風靡全球,於是dotCloud公司改名爲docker Inc,並全面投入到docker的開發之中.

2014.6 Docker發佈了第一個版本 Docker1.0

2014.7 獲得C輪融資 $4000W

2015.4 獲得D輪融資 $9500W

至今已經發布到docker 

1.2 docker國內應用史

 

 

 

由此看出,不管開發測試還是運維,絕大多數人都應該會接觸到docker.所以學docker還是很有必要的.

 

1.3 什麼是Docker

docker是一個用來裝應用的容器,就像杯子可以裝水,筆筒可以放筆,書包可以放書,可以把hello word放在docker中,可以把網站放入docker中,可以把任何想得到的程序放在docker中.

官方解釋:

 

第二章 瞭解docker

2.1 docker思想

2.1.1 集裝箱

沒有集裝箱之前運輸貨物,東西零散容易丟失,有了集裝箱之後貨物不容易丟失,我們可以把貨物想象成程序,目前我們要把程序部署到一臺新的機器上,可能會啓動不起來,比如少一些配置文件什麼的或者少了什麼數據,有了docker的集裝箱可以保證我們的程序不管運行在哪不會缺東西.

2.1.2 標準化

1. 運輸方式

docker運輸東西有一個超級碼頭,任何地方需要貨物都由鯨魚先送到超級碼頭,然後再由鯨魚從超級碼頭把貨物送到目的地去.對應的技術來說,比如我們要把臺式機的應用部署到筆記本上,我們可能選擇用QQ發過去或者用U盤拷過去,docker就標準化了這個過程,我們只需在臺式機上執行一個docker命令,把鯨魚派過來,把程序送到超級碼頭去,再在筆記本上執行一個docker命令,然後由鯨魚把程序從超級碼頭送到筆記本上去.

2. 存儲方式

當我們把程序存儲到筆記本上時,我們需要一個目錄,且我們要記住這個目錄,因爲下次我們可能還要修改,有了docker之後我們就不用記住了程序在哪裏了,我們使用的時候只需要一條命令就行了.

3. API接口

docker提供了一系列rest api的接口,包含了對docker也就是對我們的應用的一個啓動停止查看刪除等等,如當我們要啓動tomcat時我們要執行startup命令,當我們要停止時要執行shutdown命令,如果不是tomcat,我們可能還需要一些別的命令.有了docker我們記docker的命令就可以對其進行操作.

2.1.3 隔離

我們在使用虛擬機時有自己的cpu,硬盤,內存,完全感覺不到外面主機的存在,docker也差不多,不過它更輕量,我們創建虛擬機可能要幾分鐘,但是docker只需要一秒.最底層的技術時linux一種內核的限制機制,叫做LXC,LXC是一種輕量級的容器虛擬化技術.最大效率的隔離了進程和資源.通過cgroup,namespace等限制,隔離進程組所使用的物理資源,比如CPU,MEMORY等等,這個機制在7,8年前已經加入到linux內核了,直到2013年docker出世的時候才火起來,大家可能奇怪爲什麼這麼好的技術埋沒這麼多年都沒人發現呢?英雄造時勢,時勢造英雄,如果沒有云計算,敏捷開發,高頻度的彈性伸縮需求,沒有IT行業這麼多年長足的發展,也就沒有docker.

2.2 docker解決的問題

2.2.1 系統環境不一致

開發:我本地沒問題.運維:服務器沒問題. 這個問題就變成了皮球.

如果一個應用要正常的啓動起來需要什麼?比如java web應用.

需要一個操作系統,操作系統之上要jdk,tomcat,我們的代碼,配置文件.

操作系統的改變可能會導致我們的應用開不起來,比如我們調用了某些系統命令.

jdk版本也可能導致程序的運行失敗.比如class文件需要1.7編譯,我們裝了個1.6的jdk.

tomcat版本也能導致失敗,比如舊的版本一些配置在新版本中不再支持.

代碼的話就比如應用了C盤,D盤的一個文件,或者是用了系統的一些環境編碼.

配置的話我們可能少了某個配置文件等等.

下面docker來了,它把操作系統,jdk,tomcat,代碼,配置全部放到集裝箱裏.再打包放到鯨魚上,由鯨魚給我們送到服務器上,在我的機器上怎麼運行,在別的機器上也怎麼運行.不會有任何的問題.一句話就是docker解決了運行環境不一致所帶來的問題.

2.2.2 系統好卡,哪個哥們又寫死循環了

如果有根別人共用服務器的同學可能有這樣的體會,莫名其妙發現自己的程序掛了,一查原因要不是內存不夠了,要不是硬盤滿了,還有就是發現某個服務變慢了,甚至敲終端都比較卡,但是linux本身就是一個多用戶的操作系統本身就可以供多個用戶使用,docker的隔離性可以解決這個問題,就算別人的程序還是死循環瘋狂吃CPU,還是封裝瘋狂打日誌把硬盤佔滿,還是內存泄漏,把內存佔滿,都不會導致我們的程序運行錯誤.因爲docker在啓動的時候就限定好了,它最大使用的CPU硬盤,如果超過了,就會殺掉對應進程.

2.2.3 雙11來了,服務器撐不住了

大部分系統業務量並不是每天都比較平均的,特別是一些電商系統,每天總有那麼幾天業務量是平時的幾倍甚至幾十倍,如果按雙11的規模去準備服務器那麼對於平時的規模來說又是極大的浪費,所以就在節日前臨時擴展機器,過完節再把多餘的節點下線,這就給運維帶來了非常大的工作量,一到過節就在各個機器上部署各種各樣的服務,我們啓動程序需要java,tocmat等等,並且還可能起不來還要調試,這是非常噁心的工作,有了docker一切都變得美好了,只要點一下服務器就可以從10臺變成100臺甚至1000,1W臺.都是分分鐘的事情.

爲什麼會這麼快呢?都是用標準的方式把我們的程序運過來,下載過來,再用標準的方式把它運行起來,就可以做到只要在每臺機器上都執行一兩條命令,就可以讓程序正常跑起來,並且不用擔心有問題.


第三章 走進docker

鏡像就是上面說的集裝箱,倉庫就是超級碼頭,容器就是我們運行程序的地方.docker運行程序的過程就是去倉庫把鏡像拉到本地,然後用一條命令把鏡像運行起來變成容器.

build:構建,就是構建鏡像.

ship:運輸,運輸鏡像,從倉庫和主機運輸.

run:運行的鏡像就是一個容器.

build,ship,run和鏡像,倉庫,容器是一一對應的.

3.1 鏡像

鏡像的英文名交image.前面我們講到了集裝箱,鯨魚拖着的所有集裝箱就是一個鏡像.

從本質上來說鏡像就是一系列文件,可以包括我們應用程序的文件,也可以包括我們應用的運行環境的文件,既然是文件,那麼是以什麼樣的格式在本地保存的呢?

說到存儲格式,就要提到linux的一個存儲技術,叫做聯合文件系統,是一種分層的文件系統,可以將不同的目錄掛到同一個虛擬文件系統下.

比如test1下有三個文件夾,test2下有兩個文件夾,還有一個readme文件.聯合文件系統就是可以在一個文件夾(test)中看到多個文件夾(test1,test2)中的內容.

通過這種方式可以實現文件的分層,test1可以把它看作第一層,test2可以把它看作第二層,每一層有每一層自己的文件,docker就是利用了這種分層的概念實現了鏡像存儲.

下圖就是鏡像的存儲格式,這張圖是分層的,最下面一層,上面也是一層層的好像集裝箱羅列在一起.這就是鏡像最直觀的存儲方式.下面是操作系統的引導,上面是linux操作系統,再上面是一些相關的軟件,如果是我們自己的程序,就可以是tomcat,jdk,再往上是應用代碼,每一層是我們自己都可以控制得,最上面一層先忽略不看,因爲這是和容器有關的.注意一點,docker鏡像系統的每一層都是隻讀的,然後把每一層加載完成之後這些文件都會被看成是同一個目錄,相當於只有一個文件系統.docker的這種文件系統被稱之爲鏡像.

圖1

 

3.2 容器

爲了便於理解,大家可以把容器想象成虛擬機,每個虛擬機都有自己的文件系統,可以把圖1整個一部分看成是文件系統,與虛擬機系統的區別是這裏面的文件系統是一層一層的,並且最下面的n層都是隻讀的,只有上面一層是可寫的.爲什麼要有可寫的這層呢?大家的程序運行起來,勢必會要寫一些日誌,寫一些文件,或者對系統的某一些文件做一些修改,所以容器在最上面一層創建了可讀可寫的文件系統.

在程序的運行過程中,如果要寫鏡像文件時,因爲鏡像的每一層都是隻讀的,它會把文件的每一層拷到文件的最上層,然後再對它進行修改,修改之後,當我們的應用讀一個文件時會從頂層進行查找,如果沒有才會找下一層.

由於容器的最上一層是可以修改的,鏡像是不能修改的,這樣就能保證鏡像可以生成多個容器獨立運行,沒有任何干擾.

3.3 倉庫

我們的鏡像是要在其它機器上運行,如何進行傳輸呢?

這就用到了docker倉庫,我們要先把我們的鏡像傳到docker倉庫中,再由目的地把docker倉庫拉過去,這就完成了這樣的一次傳輸過程.

誰提供了這樣的倉庫呢?docker自己提供了,hub.docker.com,但是非常慢,爲了解決這個問題,國內很多公司也在做自己的倉庫.比較知名的是由網易蜂巢提供的 https://c.163yun.com/hub#/m/home/

 

第四章 centos下docker安裝

因爲我這裏使用的是centos所以就在centos下安裝.

參考博客與網站:

https://www.jb51.net/article/161580.htm

https://blog.csdn.net/jsnhux/article/details/89847109

https://docs.docker.com/install/linux/docker-ce/centos/

 

 

1. Docker 要求 CentOS 系統的內核版本高於 3.10,查看本頁面的前提條件來驗證你的CentOS 版本是否支持 Docker 。

通過 uname -r 命令查看你當前的內核版本

2.  如果安裝過請先卸載

yum remove docker \
           docker-client \
           docker-client-latest \
           docker-common \
           docker-latest \
           docker-latest-logrotate \
           docker-logrotate \
           docker-engine

3.安裝依賴設置yum倉庫

安裝依賴:

yum install -y yum-utils \
  device-mapper-persistent-data \
  lvm2

設置倉庫:

yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo

4. 安裝docker

yum install docker-ce docker-ce-cli containerd.io

5. 啓動並加入開機啓動

systemctl start docker
systemctl enable docker

6.驗證是否安裝成功

docker version
docker run hello-world

顯示如下即安裝成功! 

[root@iZ2ze68ge5c1uwlkmnb9ixZ zcapp]# docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
1b930d010525: Pull complete 
Digest: sha256:0e11c388b664df8a27a901dce21eb89f11d8292f7fca1b3e3c4321bf7897bffe
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/


第五章 docker初體驗

5.1 docker基本命令

1.docker pull [options] NAME[:TAG]

通過此命令可以docker遠程倉庫拉取鏡像到本地.

name是拉取鏡像的名稱,:TAG表示是可選的,如果不選表明時latest,如果選擇表明是指定版本的.

options是拉去的一些參數.

當不加請求地址的時候回去docker的官網拉取鏡像.

2.docker images [options] [REPOSITORY[:TAG]]

options是選項,後面是指定鏡像的名稱.這個用的不多,可能當本地鏡像非常多的時候要指定查看某一個鏡像.

IMAGE ID 其實是一個64位的字符串,它可以唯一標識我們的鏡像,這裏只顯示了16位,後面的被截掉了.

3. docker run [options] IMAGE[:TAG] [COMMAND] [ARG..]

IMAGE是鏡像的名字

COMMAND是運行起來的時候要執行什麼命令.

ARG表示這條命令運行需要的參數.

5.2 docker運行鏡像流程

docker pull:首先docker pull向docker daemon發送了一條命令pull,告訴docker daemon要拉取某一個鏡像,docker daemon會在本機檢查鏡像是否存在,如果存在且版本就是我們想要拉取的版本,它就不會做任何的操作.如果不存在下一步它會到docker的倉庫中找我們要拉取的鏡像名字,如果找到了就會有docker倉庫傳送到我們的本地,把我們要的鏡像傳送到我們的本地來.

docker run:首先把命令發送到我們的docker daemon,docker daemon會先檢查鏡像在本機是否存在,如果不存在相當於執行了一個docker pull的過程,下載回來之後會以一定方式把鏡像運行起來變成docker容器.


第六章 docker運行nginx

6.1 運行nginx鏡像

我們打開網易蜂巢鏡像中心 https://c.163yun.com/hub#/m/home/

搜索nginx,可以看到有兩個nginx,他們的名字和頭上和圖標都不一樣,一個是鯨魚,一個是兩個球.

帶有鯨魚的鏡像表示這個鏡像是從官網的鏡像中心複製過來的.這個鏡像與docker的鏡像是一摸一樣的.我們使用此鏡像.

點進去,會有下載地址,複製裏面的地址,然後拉取鏡像.

複製到系統中運行.

運行完後可以查看鏡像狀態

在前臺運行容器命令如下,輸入後容器就會運行,按ctrl+c可以終止容器的運行.

docker run hub.c.163.com/library/nginx

在後臺運行容器:

docker run -d hub.c.163.com/library/nginx

查看運行的容器:

docker ps

更多關於運行的命令:

docker run --help

因爲我們在平時運行的時候需要調試容器內部的設置、查看一下日誌等等.我們可以通過如下命令進入容器內部:

命令的大體內容:

命令具體內容: 

docker exec -it 02963d2002b bash

 -i保證我們的輸入有效,即使在沒有detach的情況下也能運行.

-t表示將分配給我們一個僞終端.我們將在僞終端輸入我們的內容.

後面跟着的是容器的id,即我們上面用ps查詢出來的id,這個id可以少寫幾位,它會自動識別.

可輸入如下命令瞭解更多:

docker exec --help

輸入命令後發現我們前面的標識也變了,相當於進入了一個新的電腦.

可以查詢一下nginx在什麼位置

which nginx

打開ps查看一下當前運行的進程.我這裏提示沒有ps命令.我從網上查了一下發現是因爲當前系統沒有安裝這個命令,然後我安裝了一下.從命令可以看出,這個nginx容器附帶的系統應該是ubuntu不是centos.

安裝ps命令:

apt-get update

apt-get install procps

利用ps命令查看進程,可以發現nginx已經在運行了.

ps -ef

輸入 exit即可退出返回原來的系統. 

6.2 docker網絡

6.2.1 網絡介紹

上面我們只運行了nginx,並沒有用瀏覽器進行訪問,這裏我們嘗試用瀏覽器訪問,但是之前我們要了解一下docker網絡.

我們直到docker的隔離性,網絡也是個隔離性的一部分,linux使用了命名空間來進行資源的隔離,比如pid namespace就是用來隔離進程的,mount namespace是用來隔離文件系統的,network namespace 是用來隔離網絡的.每一個network namespace都提供了一個獨立的網絡環境,包括網卡路由iptable規則等等,都是與以其它的network space隔離的.

1. docker容器在默認情況下,一般會分配一個獨立的network-namespace,也就是網絡類型中的Bridge模式.

在使用Bridge時就涉及到了一個問題,既然它有獨立的namesapce,這就需要一種技術使容器內的端口可以在主機上訪問到,這種技術就是端口映射,docker可以指定你想把容器內的某一個端口可以在容器所在主機上的某一個端口它倆之間做一個映射,當你在訪問主機上的端口時,其實就是訪問容器裏面的端口.

2. 還有一種類型是Host模式,如果在啓動容器的時候指定使用Host模式,那麼這個容器將不會獲得一個獨立的network namespace,而是和主機共同使用一個,這個時候容器將不會虛擬出自己的網卡,配置出自己的ip.而是使用宿主機上的ip和端口.也就是說在docker上使用網絡和在主機上使用網絡是一樣的.

3. 還有一種網絡類型是None.也就是沒有網絡,這種情況docker將不會和外界的任何東西進行通訊.

6.2.2 實際訪問端口

剛纔我們在運行nginx鏡像的時候並沒有指定端口映射,所以我們這裏停掉nginx容器.

docker stop containerId

1. -p(小寫)是開放一個容器的端口到主機上

在後臺運行,開放主機8080端口映射到容器的80端口上.

docker run -d -p 8080:80 hub.c.163.com/library/nginx

查看主機8080端口是否開啓

netstat -na |grep 8080

 

是開啓的那麼訪問 主機ip:8080 即可訪問到nginx.

 

2. -P(大寫)是開放容器所有的端口到主機上一個隨機的端口.

停掉剛纔的docker服務.

使用大P

docker run -d -P hub.c.163.com/library/nginx

可以看到隨機給我的端口是32768 

然後用 ip:32768去訪問即可訪問到nginx. 


第七章 docker部署第一個java web應用

我們還需要學習Dockerfile,它告訴docker我們怎樣製作我們的鏡像,我們鏡像的每一步操作分別是什麼,寫好Dockerfile後我們私用docker build命令執行Dockerfile裏面的每一件事情.最終會把Dockerfile構建出來.

在這裏因爲是做一個演示,所以我們使用了一個開源的java web應用Jpress.

7.1 製作自己的鏡像

1. 從網易的鏡像中心找一個tomcat的鏡像

docker pull hub.c.163.com/library/tomcat:latest

因爲tomat鏡像肯定有jdk,所以我們就不用單獨再裝jdk了.

 

2.編寫dockerfile

我們需要建立一個dockerfile告訴docker需要做什麼,這裏我建立了Dockerfile,並將我們的web文件放到了和它同一個目錄下.

首先我們的鏡像是要運行在tomcat中的,所以填寫 from tomcat,以tomcat爲基礎.maintainer是所有者的意思.因爲war包是要放在webapps中的,所以我們使用copy命令複製到tomcat的webapps.

爲什麼webapps在local中?我們可以去下載鏡像的網站查詢,向下拉就好了.具體網址 : https://c.163yun.com/hub#/m/repository/?repoId=2955

這裏說一個個人猜想,每個容器都包含一個自己的系統,所以這裏的/usr/local/tomcat/webapps指的是tomcat容器中的位置,那麼哪裏指定是tomcat容器呢?就是在一開始的from指定的.

from hub.c.163.com/library/tomcat

maintainer zhangchen [email protected]

COPY jpress.war /usr/local/tomcat/webapps

3.構建容器

注意這裏是有個點的,點標明是在根據當前目錄構建

docker build .

可以使用docker images查看鏡像是否build成功

發現一個none,表明構建成功了.

可以重新構建給它起個名字 -t是給鏡像指定一個tag

docker build -t jpress:latest .

更多的參數查詢:

docker build --help

 

7.2 運行自己的鏡像

運行我們製作的鏡像並指定端口

docker run -d -p  8080:8080 jpress

訪問我們的網站,發現網站已經可以正常訪問了.

然後發現它要求我們安裝自己的數據庫,所以我們利用docker安裝mysql.

在鏡像中心搜索並拉取mysql

 docker pull hub.c.163.com/library/mysql:latest

在鏡像中心查看配置,並配置root用戶密碼

docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 hub.c.163.com/library/mysql

 發現我們沒有創建數據庫,於是停止這個容器的運行,並在與劇中創建jpress數據庫.

docker stop 4be94fb2df1d3a28c1
ocker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=jpress hub.c.163.com/library/mysql

這樣我們的數據庫就建立成功了.

進入網站後要輸入網站信息,輸入數據庫地址時,注意不要輸入localhost,因爲我們jpress是運行在容器內的,我們會訪問tomcat容器內的3306,我們應該用ifconfig查詢我們本機的ip地址.我這裏的內網ip是172.17.10.68

 

以上都做完後,我們的網站就可以跑起來了.

http://59.110.164.62:8080/jpress/

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章