企业——Docker容器的搭建及简单应用
1.環境需求
不需要開虛擬機,只需要一個真機就行。
下載docker的安裝包,可以在官網上下載? www.docker.com
?? yum install -y pigz-2.3.4-1.el7.x86_64.rpm docker-ce-18.03.1.ce-1.el7.centos.x86_64.rpm container-selinux-2.21-1.el7.noarch.rpm?? ##因為有依賴性,所以有時候需要把安裝包全部下載 yum install -y *
2.docker的基礎知識
(1)Docker與虛擬機比較:
?? kvm 完全虛擬化,修改虛擬機,不對外部機有影響,完全和真機隔離?? docker 操作系統的特殊進程,部分隔離.docker(s) 比 kvm(min) 要快,也比kvm小
?? 作為一種輕量級的虛擬化方式,Docker在運行應用上跟傳統的虛擬機方式相比具有顯著優勢:
?? -Docker容器很快,啟動和停止可以在秒級實現,這相比傳統的虛擬機方式要快得多。
?? -Docker容器對系統資源需求很少,一臺主機上可以同時運行數千個Docker容器。
?? -Docker通過類似Git的操作來方便用戶獲取、分發和更新應用鏡像,指令簡明,學習成本較低。
?? -Docker通過Dockerfile配置文件來支持靈活的自動化創建和部署機制,提高工作效率。
(2)docker的核心概念
?? 鏡像(Image)
?? -- 就是一個只讀的模板。鏡像是只讀的,鏡像中包含有需要運行的文件。例如:一個鏡像可以包含一個完整的操作系統環境,里面僅安裝了 Apache 或用戶需要的其它應用程序。鏡像可以用來創建 Docker 容器,一個鏡像可以創建很多容器。Docker 提供了一個很簡單的機制來創建鏡像或者更新現有的鏡像,用戶甚至可以直接從其他人那里下載一個已經做好的鏡像來直接使用。
?? 倉庫(Repository)
?? -- 是集中存放鏡像文件的場所。有時候會把倉庫和倉庫注冊服務器(Registry)混為一談,并不嚴格區分。實際上,倉庫注冊服務器上往往存放著多個倉庫,每個倉庫中又包含了多個鏡像,每個鏡像有不同的標簽(tag)。倉庫分為公開倉庫(Public)和私有倉庫(Private)兩種形式。最大的公開倉庫是 Docker Hub,存放了數量龐大的鏡像供用戶下載。國內的公開倉庫包括 時速云 、網易云 等,可以提供大陸用戶更穩定快速的訪問。當然,用戶也可以在本地網絡內創建一個私有倉庫。當用戶創建了自己的鏡像之后就可以使用 push 命令將它上傳到公有或者私有倉庫,這樣下次在另外一臺機器上使用這個鏡像時候,只需要從倉庫上 pull 下來就可以了。
?? 容器(container)
?? -- Docker 利用容器(Container)來運行應用。容器是從鏡像創建的運行實例。它可以被啟動、開始、停止、刪除。每個容器都是相互隔離的、保證安全的平臺。可以把容器看做是一個簡易版的 Linux 環境(包括root用戶權限、進程空間、用戶空間和網絡空間等)和運行在其中的應用程序。容器的定義和鏡像幾乎一模一樣,也是一堆層的統一視角,唯一區別在于容器的最上面那一層是可讀可寫的。容器是Docker的運行組件,啟動一個鏡像就是一個容器,容器是一個隔離環境,多個容器之間不會相互影響,保證容器中的程序運行在一個相對安全的環境中。
Docker鏡像是由文件系統疊加而成。最底端是一個文件引導系統,即bootfs。Docker用戶不會與引導文件系統有直接的交互。Docker鏡像的第二層是root文件系統rootfs,通常是一種或多種操作系統,例如ubuntu等。在Docker中,文件系統永遠都是只讀的,在每次修改時,都是進行拷貝疊加從而形成最終的文件系統。Docker稱這樣的文件為鏡像。一個鏡像可以迭代在另一個鏡像的頂部。位于下方的鏡像稱之為父鏡像,最底層的鏡像稱之為基礎鏡像。最后,當從一個鏡像啟動容器時,Docker會在最頂層加載一個讀寫文件系統作為容器。Docker的這種機制我們稱之為寫時復制。
?
對docker的啟動需要容器,需要鏡像,倉庫。
倉庫(私有和公共)registry——>鏡像images——>容器container——>提交之后——>保存到倉庫registry里
?
(3)什么是Docker?
Docker 是一個開源的應用容器引擎,讓開發者可以打包他們的應用以及依賴包到一個可移植的容器中,然后發布到任何流行的?Linux?機器上,也可以實現虛擬化。容器是完全使用沙箱機制,相互之間不會有任何接口。Docker 屬于 Linux 容器的一種封裝,提供簡單易用的容器使用接口。它是目前最流行的 Linux 容器解決方案。Docker 將應用程序與該程序的依賴,打包在一個文件里面。運行這個文件,就會生成一個虛擬容器。程序在這個虛擬容器里運行,就好像在真實的物理機上運行一樣。有了 Docker,就不用擔心環境問題。Docker容器的運行不需要額外的虛擬化管理程序(Virtual Machine Manager,VMM,以及Hypervisor)支持,它是內核級的虛擬化,可以實現更高的性能,同時對資源的額外需求很低。
?
(4)一個完整的Docker具有什么?
一個完整的Docker有以下幾個部分組成:
Docker Client 客戶端
Docker Daemon 守護進程
Docker Image 鏡像
Docker Container 容器
?
Docker是CS架構,主要有兩個概念:
- Docker daemon: 運行在宿主機上,Docker守護進程,用戶通過Docker client(Docker命令)與Docker daemon交互
- Docker client: Docker 命令行工具,是用戶使用Docker的主要方式,Docker client與Docker daemon通信并將結果返回給用戶,Docker client也可以通過socket或者RESTful api訪問遠程的Docker daemon
?
?
3.docker對于game2048的部署
下載一個game2048.tar
還有所需要的鏡像? rhel7
?? docker load -i game2048.tar? ##導入game2048的鏡像
?? docker images?? ##列出了所有頂層(top-level)鏡像。查看宿主機上的鏡像,Docker鏡像保存在/var/lib/docker目錄下。
?? ip addr?? ##在docker開啟以后,會自動生成docker0的ip
?? docker run -d --name vm1 game2048??? ##生成一個vm1的容器? -d打入后臺? 利用game2048鏡像
?? docker ps??? ##查看添加的容器
?? docker inspect vm1?? ##查看添加的容器vm1?會自動的給Docker分配ip,如下圖:
?? 注意:docker inspect <container-id> or <image-id>:docker inspect命令會提取出容器或者鏡像最頂層的元數據
?? 測試:在網頁上輸入 172.17.0.2? 就會出來game2048的游戲界面
??
?
?
4.docker創建容器的命令
?? 導入鏡像:
?? docker load -i ubuntu.tar
?? docker load -i rhel7.tar
?? 創建容器:
?? docker run -d --name vm1 rhel7?? ##創建vm1容器,利用rhel7的鏡像
?? docker run -it --name vm2 ubuntu??? ## -it 具有交互界面
?? docker run -it --name vm3 rhel7 bash?? ##必須加bash才會出現交互界面
?? 注意:docker run <image-id>: docker run就是docker create和docker start兩個命令的組合,支持參數也是一致的,如果指定容器名字時,容器已經存在會報錯,可以增加 --rm 參數實現容器退出時自動刪除。
??
?? 查看容器: docker ps 查看創建的全部的容器:docker?ps -a
====================================================================================
?? 注意:虛擬機的ip是順序分配的。剛開始的docker啟動之后,會自動添加一個docker0:172.17.0.1,在之后創建的容器,會按照創建的順序依次分配ip,比如:vm1的game2048的ip就是 172.17.0.2 ,到現在創建的vm2的ip就會分配為 172.17.0.3
====================================================================================
5.docker容器的交互界面的退出及容器(鏡像)的刪除
?? (1)退出
?? ctrl+P+Q? ##退出進程但是不停止,在ps的時候可以看到進程信息
?? ctrl+D? ##直接退出,在ps的時候看不見正在運行的進程
?? (2)刪除
?? <1>容器的刪除
?? docker rm vm1??? ##有時容器正在運行,就會出現刪除不了的情況?
?? docker rm -f vm1?? ##出現刪除不了的情況時,需要 -f 強制刪除
?? docker container prune?? ##將所有已經暫停的容器全部刪除
?? docker rm ‘docker ps -aq‘?
?? <2>鏡像的刪除
?? docker rmi 鏡像的名稱
6.容器退出后的鏈接
?? 情況一:ctrl+P+Q 退出
?? docker attach vm2
?? ls
?? touch file{1..20}
??
?? 情況二:ctrl+D 退出 這個直接將容器關閉了,而不是打入后臺運行,所以 attach 連接不上
?? docker attach vm2?? ##會顯示鏈接失敗,vm2是一個停止運行的容器,所以需要先開啟
?? docker start vm2 ##應為是全部的關閉,所以需要先開啟,在連接
?? docker attach vm2
?? ls??? ##剛才建立的文件依舊存在
====================================================================================
?? 注意:一旦容器被刪除,再創建一個名字一樣的容器是沒用的,容器內的建立的文件已經不存在了,如果需要保存的話,可以將容器commit保存一下
?? docker commit <container-id>: 將容器的可讀寫層轉換為一個只讀層,這樣就把一個容器轉換成了不可變的鏡像。
====================================================================================
?? 退出以后保存,轉化成新的鏡像:??
docker commit? vm2? ubuntu:v1
?? docker history ubuntu
?? docker history ubuntu:v1
?? 可以看出兩個鏡像的不同,v1多了一層,就是新建的文件,保存下來了,這樣用這個新的鏡像,創建出來的容器都會含有新建的文件的這一層,如果不想要這一層文件,可以將 v1 這個鏡像刪除。
?? 轉換成新的鏡像之后:
?? docker rm vm2
?? docker run -it --name vm2 ubuntu:v1
?? ls?? ##文件層存在
7.docker的基礎命令
?? docker images?? ##列出了所有頂層(top-level)鏡像。
?? docker load -i?? ##導入鏡像
?? docker run --name?? ##創建一個容器并運行
?? docker ps?? ##顯示當前的并且正在運行的容器???
?? docker ps -a?? ##查看存在的但是沒有運行的容器
?? docker run -it(交互式) --name?? ##交互式的,bash是用來交互的解釋器
?? docker rm?? ##刪除容器,但是在線情況下的容器不能刪除,但是-f可以強制
? ? ? ? ? ? ? 注意:鏡像當中的是只讀的,容器是在鏡像的基礎之上的寫入自己獨有的命令
?? docker rmi?? ##刪除鏡像
?? docker history game2048:lastest?? ##查看歷史
?? docker -d??? ##打入后臺
?? docker inspect vm1??
?? docker commit vm ubuntu:v1?? ##提交,會生成新的鏡像,并命名為v1
?? docker configs?? ##是用來的管理的
?? docker container?? ##是管理的子命令,和上層的一樣,專門針對容器操作的
?? docker cp /etc/passwd vm2:/tmp?? ##物理機和容器之間復制文件
?? docker exec? ##不需要登陸,在外部直接運行一些指令
?? docker export?? ##針對對象是容器,輸出,轉換成鏡像文件,共享鏡像
?? docker logs?? ##查看,記錄在容器內執行的任何操作
?? docker network?? ##顯示容器網絡
?? port? docker -p?? ##端口映射?? 8080:80? 物理機的:容器的
?? docker top?? ##顯示容器內的進程
8.docker的exec的示例:
?? 如果不知道docker exec的用法,可以使用docker exec --help 來查看。
?? docker cp /etc/passwd vm2:/tmp?? ## 物理機和容器之間復制文件
?? docker attach vm2
?? ls
?? cd /tmp
?? ls??? ##就可以看到cp進來的文件
?? docker exec vm2 ls /passwd?? ##直接就可以查看容器內的文件,不需要建立連接。
?? docker exec vm2 rm /passwd?? ##直接就可以刪除容器內的文件? ?,不需要建立連接。
9.docker的port的示例:
?? docker run -d --name vm1 -p 8080:80 game2048
??? ## -p 進行端口映射,真機的8080端口,映射到容器的80端口? Docker的端口映射是由 iptables 來實現的
?? docker port vm1??? ##用來查看端口映射
?? 測試:在網頁上輸入 172.25.254.9:8080?? 會出現game2048的游戲界面
10.使用官方的鏡像加速器
為什么要使用鏡像加速器?我們使用Docker的第一步,應該是獲取一個官方的鏡像,例如mysql、wordpress,基于這些基礎鏡像我們可以開發自己個性化的應用。我們可以使用Docker命令行工具來下載官方鏡像。但是因為網絡原因,我們下載一個300M的鏡像需要很長的時間,甚至下載失敗。因為這個原因,阿里云容器Hub服務提供了官方的鏡像站點加速官方鏡像的下載速度
?? 在網頁上:www.aliyun.com? 登陸注冊 —> 管理控制臺 -> 鏡像庫 -> 鏡像加速器
?? cd /etc/docker/
?? vim daemon.json
??? {
??? ?? "registry-mirrors": ["https://vo5twm71.mirror.aliyuncs.com"]
??? }?
?? systemctl daemon-reload
?? systemctl restart docker
?? systemctl status docker
11.docker中的nginx的部署
?? (1)導入鏡像并創建新的容器vm1
?? docker search nginx ##在官方的倉庫中下載相應需要尋找的鏡像
?? docker pull nginx ##將找到的鏡像拉取到本地的物理機上,物理機上的某一個特定的目錄下面,docker的鏡像的目錄,可以訪問的。
?? docker run -d --name vm1 -p 8080:80 nginx ##創建一個新的容器vm1和物理機的8080端口相映射。
?? docker ps ##命令查看創建的新的容器vm1 ps查看活躍的容器 ps -a查看全部的容器
??? 59b9de50f4b5??????? nginx??? ???????????"nginx -g 'daemon of…"?? 3 seconds ago?????? Up 2 seconds??????? 0.0.0.0:8080->80/tcp?? vm1
?? docker port vm1 ##查看vm1的端口的信息
? ?? 80/tcp -> 0.0.0.0:8080
?? 測試:在網頁上輸入 172.25.254.9:8080
?
?? (2)nginx的發布頁面的修改:
?? 方法一:可以在物理機上的某一個目錄下,創建一個新的發布文件,發送到docker的默認的發布目錄中
?? cd /tmp ##在物理機中
?? mkdir docker
?? cd docker/
?? vim index.html
??? server
?? docker cp index.html vm1:/usr/share/nginx/html
??
?? 測試:在網頁上輸入 172.25.254.9:8080? ##注意要清除網頁的緩存
?? 方法二:直接掛載,將物理機的目錄掛載在docker容器的默認的發布目錄下
?? cd /tmp/docker
?? mkdir web
?? mv index.html web/
?? docker rm vm1
?? docker run -d --name vm1 -p 8080:80 -v /tmp/docker/web/:/usr/share/nginx/html nginx?? ##將主機的目錄/tmp/docker/web/作為容器的數據卷掛載到容器中,使宿主機和容器之間可以共享一個目錄。以后就可以直接修改主機的目錄,容器的發布目錄也會跟著改變
12.數據卷管理
?? 數據卷(Data Volumes)是一個可供容器使用的特殊目錄,它提供了很多有用的特性:對數據卷的修改會立馬生效,數據卷會一直存在,直到沒有容器使用,數據卷可以被多個容器使用,數據卷類似于Linux的mount。實質是在當前機器映射了一個目錄到容器內部。
?? 數據卷容器(Data Volume Dontainers)其實就是一個普通的容器,只是我們專門用它提供數據卷供其它容器掛載使用。使用--volumes-from指定數據卷容器。多個--volumes-from將掛載多個數據卷容器。
?? 注意:使用--volumes-from參數所掛載的數據卷容器本身并不需要保持運行狀態。如果刪除了掛載的容器,數據卷并不會被自動刪除,如果要刪除一個數據卷,必需使用docker rm -v命令來指定同時刪除管聯的容器。
?? docker run 在創建容器時使用 -v 參數可以掛載一個或多個數據卷到當前運行的容器中,-v的作用是將宿主機上的目錄作為容器的數據卷掛載到容器中,使宿主機和容器之間可以共
享一個目錄。
?? (1)掛載數據卷到新創建的容器上:
??? docker run -it --name vm1 -v /tmp/data1:/data1 -v /tmp/data2:/data2 rhel7 /bin/bash
??? ##-v 參數可以重復使用,掛載多個數據卷到容器中,冒號前面的是宿主機的目錄(本地目錄不存在 docker 會自動創建),冒號后面的是容器中的掛載目錄。docker commit 時卷的數據不會被保存。
?? (2)默認掛載可以讀寫數據卷,也可以只讀掛載:
?? docker run -it --name westos2 -v /tmp/data2:/data2:ro rhel7 /bin/bash
?? (3)掛載宿主機文件:
?? docker run -it --name vm2 -v /etc/yum.repos.d/rhel-dvd.repo:/etc/yum.repos.d/rhel-dvd.repo:ro rhel7 /bin/bash
?? (4)數據卷容器:
?? docker create --name data -v /tmp/sharedata:/sharedata rhel7 /bin/true
?? docker run -it --name vm1 --volumes-from data rhel7 /bin/bash
?? docker run -it --name vm2 --volumes-from data rhel7 /bin/bash
?? 示例1:數據卷的掛載
?? docker ps?? ##刪除沒有用的容器
?? docker run -it --name vm1 -v /tmp/docker/dvd.repo:/etc/yum.repos.d/dvd.repo:ro -v /tmp/docker/data1:/data1 -v /tmp/docker/data2:/data2 rhel7
??? ##創建一個叫vm1的容器,將主機的dvd文件掛載到容器內的yum源的默認目錄下,再掛載兩個目錄到容器內,ro代表只讀掛載。
?? bash-4.2# ls?? ##會顯示出掛載的文件或是目錄
?? bash-4.2# cd data1?? ##進入到掛載的目錄下,創建文件,文件是寫入到主機的
?? bash-4.2# touch file1
?? bash-4.2# cd ..
?? bash-4.2# cd data2?? ##進入到掛載的目錄下,創建文件,文件是寫入到主機的
?? bash-4.2# touch file2
?? bash-4.2# cd /etc/yum.repos.d/?? ##只讀掛載了真機的yum源文件
?? bash-4.2# ls
?? bash-4.2# cat dvd.repo?? ##只讀掛載,因此可以 cat
?? bash-4.2# rm -fr dvd.repo?? ##但是,執行其他操作就會報錯
??? rm: cannot remove 'dvd.repo': Device or resource busy
?? bash-4.2# yum repolist?? ##因為掛載了yum源,所以可以下載
?? bash-4.2# yum install -y httpd?? ##下載是可以的
?? bash-4.2# /usr/sbin/httpd?? ##開啟httpd服務
?? bash-4.2# netstat -antlp?? ##查看端口是否被開啟
?? bash-4.2# cd /var/www/html/
?? bash-4.2# echo wf > index.html
??
?? 測試:在網頁上輸入 172.17.0.2? ##注意要清除網頁的緩存
?? 示例2:數據卷容器的創建和使用
?? docker create --name datavol -v /tmp/docker/dvd.repo:/etc/yum.repos.d/dvd.repo:ro -v /tmp/docker/data1:/data1 -v /tmp/docker/data2:/data2 rhel7 bash
?? docker run -it --volumes-from datavol --name vm1 rhel7 bash
?? docker run -it --volumes-from datavol --name vm2 rhel7 bash
?? docker run -it --volumes-from datavol --name vm3 rhel7 bash
?? 注意:進入到容器內之后,容器內的數據是相同的
13.容器網絡模型
?? 容器有四種網絡模型:bridge 橋接模式、host 模式、container 模式和 none 模式
?? ---橋接模式:該模式下 Docker Container 不具有一個公有 IP,即和宿主機的 eth0 不處于同一個網段。導致的結果是宿主機以外的世界不能直接和容器進行通信。
???? 橋接的實現步驟如下:
??? (1) Docker Daemon 利用 veth pair 技術,在宿主機上創建兩個虛擬網絡接口設備,假設為veth0 和 veth1。而 veth pair 技術的特性可以保證無論哪一個 veth 接收到網絡報文,都會將報文傳輸給另一方。
??? (2) Docker Daemon 將 veth0 附加到 Docker Daemon 創建的 docker0 網橋上。保證宿主機的網絡報文可以發往 veth0;
??? (3) Docker Daemon 將 veth1 添加到 Docker Container 所屬的 namespace 下,并被改名為 eth0。如此一來,保證宿主機的網絡報文若發往 veth0,則立即會被 eth0 接收,實現宿主機到Docker Container 網絡的聯通性;同時,也保證 Docker Container 單獨使用 eth0,實現容器網絡環境的隔離性。
???? 示例:
?? docker run -it --name vm1 ubuntu?? ##默認的網絡模型是橋接模式,這種模式下,自動按順序分配ip
?? ---host模式:容器和物理機共享一個網絡,如何分辨訪問的是容器還是物理機?開啟的端口不一樣,網絡資源只有一份。
???? host 模式是 bridge 橋接模式很好的補充。采用 host 模式的 Docker Container,可以直接使用宿主機的 IP 地址與外界進行通信,若宿主機的 eth0 是一個公有 IP,那么容器也擁有這個公有 IP。同時容器內服務的端口也可以使用宿主機的端口,無需額外進行 NAT 轉換。當然,有這樣的方便,肯定會損失部分其他的特性,最明顯的是 Docker Container 網絡環境隔離性的弱化,即容器不再擁有隔離、獨立的網絡棧。另外,使用 host 模式的 Docker Container 雖然可以讓容器內部的服務和傳統情況無差別、無改造的使用,但是由于網絡隔離性的弱化,該容器會與宿主機共享競爭網絡棧的使用;另外,容器內部將不再擁有所有的端口資源,原因是部分端口資源已經被宿主機本身的服務占用,還有部分端口已經用以 bridge 網絡模式容器的端口映射。
???? 示例:
?? docker run -it --name vm2 --net host ubuntu?? ##設置網絡模式為host型,因此ip addr看到的網絡信息和主機的一樣,都含有docker0
?? ---自定義(container)模式:和定義的容器是網絡共享的
???? Container 網絡模式:
??? (1) 查找 other container(即需要被共享網絡環境的容器)的網絡 namespace;
??? (2) 將新創建的 Docker Container(也是需要共享其他網絡的容器)的 namespace,使用other container 的 namespace。
???? Docker Container 的 other container 網絡模式,可以用來更好的服務于容器間的通信。在這種模式下的 Docker Container 可以通過 localhost 來訪問 namespace 下的其他容器,傳輸效率較高。雖然多個容器共享網絡環境,但是多個容器形成的整體依然與宿主機以及其他容器形成網絡隔離。另外,這種模式還節約了一定數量的網絡資源。但是需要注意的是,它并沒有改善容器與宿主機以外世界通信的情況
???? 示例:
?? docker run -it --name vm3 --net container:vm1 ubuntu?? ##設置網絡模式為container型,vm1和vm3的ip 是一樣的
?? --none模式:網絡環境為 none,即不為 Docker Container 任何的網絡環境。一旦 Docker Container 采用了 none 網絡模式,那么容器內部就只能使用 loopback 網絡設備,不會再有其他的網絡資源。可以說 none 模式為 Docker Container 做了極少的網絡設定,但是俗話說得好“少即是多”,在沒有網絡配置的情況下,作為 Docker 開發者,才能在這基礎做其他無限多可能的網絡定制開發。在 none 網絡模式下可以分配固定的 ip
???? 示例:? 給容器添加固定的網絡地址
?? docker run -it --name vm4 --net none ubuntu?? ##設置網絡模式為none型,沒有ip
?? ip netns list?? ##使用方法 ip netns? help?? 查看所有 network namespace
?? docker inspect vm4 | grep Pid
?? cd /proc/5065
?? cd ns/
?? ls
?? pwd
?? ln -s /proc/5065/ns/net /var/run/netns/5065
?? ip link add name veth0 type veth peer name veth1
?? ip addr?? ##可以看到創建了一對虛擬網絡接口設備
?? ip link set up veth0
?? ip link set up veth1?? ##將兩個接口設備開啟
?? ip addr?? ##查看端口是否開啟
?? brctl addif docker0 veth0?? ##將虛擬網絡接口設備的一個與docker0鏈接
?? ip netns list
?? ip link set veth1 netns 5065?? ##將虛擬網絡接口設備的另一個與容器鏈接
?? ip netns? exec 5065 ip link set veth1 name eht0
?? ip netns exec 5065 ip addr add 172.17.0.100?? ##給容器添加ip
?? 注意:docker attach vm4 -> ip add -> ip addr add 172.17.0.100/24 dev veth1?? ##這樣添加ip是不行的,不被允許的
??
?? ip netns exec 5065 ip route add default via 172.17.0.1?? ##添加網關
14.docker安全
?? 設置特權級運行的容器:--privileged=true?? ##這個一開啟就相當于是root用戶
?? docker run -it --name vm1 ubuntu
?? root@63733880d3f0:/# ip addr
?? root@63733880d3f0:/# ip addr del 172.17.0.2/16 dev eth0
??? RTNETLINK answers: Operation not permitted
?? 上面的權限被限制了,是因為:
?? docker inspect -f {{.HostConfig.Privileged}} vm1
??? false???? ##默認的權限是關閉的,也就是說,默認的是普通用戶的身份
??
?? 因此,可以將這個設置為true,就運行了root用戶的身份,就可以刪除
?? docker run -it --name vm2 --privileged=true ubuntu?? ##創建用戶的時候,開啟權限
?? root@a8dc66fa5137:/# ip addr
?? root@a8dc66fa5137:/# ip addr del 172.17.0.2/16 dev eth0
?? root@a8dc66fa5137:/# ip addr?? ##成功刪除
15.容器間互聯:
?? --link 參數可以在不映射端口的前提下為兩個容器間建立安全連接, --link 參數可以連接一個或多個容器到將要創建的容器。
?? --link 參數的格式為 --link name:alias,其中 name 是要鏈接的容器的名稱,alias 是這個連接的別名。
16.Dockerfile的創建
=====================================================================================
?? Dockerfile文件語法
(1)FROM(指定基礎image)
?? 構建指令,必須指定且需要在Dockerfile其他指令的前面。后續的指令都依賴于該指令指定的image。FROM指令指定的基礎image可以是官方遠程倉庫中的,也可以位于本地倉庫。鏡像可以指定標簽。? 格式:FROM <image>:<tag>
(2)RUN
?? 構建指令,RUN可以運行任何被基礎image支持的命令。如基礎image選擇了ubuntu,那么軟件管理部分只能使用ubuntu的命令。RUN指令可以有多條,每條RUN指令將在當前鏡像基礎上執行指定命令,并提交為新的鏡像。當命令較長時,可以用\來換行。
(3)CMD(設置容器啟動時執行的操作)
?? 設置指令,用于容器啟動時指定的操作。該操作可以是執行自定義腳本,也可以是執行系統命令。該指令只能在文件中存在一次,如果有多個,則只執行最后一條。
?? 注意:
??? 1) CMD運行在鏡像構建之后,容器啟動的時候;
??? 2) CMD只執行最后一條
??? 3) CMD可以被用戶指定的命令覆蓋
(4)EXPOSE(指定容器需要映射到宿主機器的端口)
?? 設置指令,該指令會將容器中的端口映射成宿主機器中的某個端口。格式為:
?? 例如:
?? EXPOSE 80 443 11211?? ##告訴Docker服務端容器暴露的端口號,供互聯系統使用。在啟動容器時需要通過-P,Docker主機會自動分配一個端口轉發到指定的端口;使用-p,則可以具體指定哪個本地端口映射過來。
(5)ENV(用于設置環境變量)
?? 構建指令,在image中設置一個環境變量。格式:
??? ENV <key> <value>
?? 設置了后,后續的RUN命令都可以使用,容器啟動后,可以通過docker inspect查看這個環境變量,也可以通過在docker run --env key=value時設置或修改環境變量。
(6)ADD(從src復制文件到容器的dest路徑)
?? 構建指令,所有拷貝到容器中的文件和文件夾權限為0755,uid和gid為0。格式為:
??? ADD <src> <dest>??? ## <src> 是相對被構建的源目錄的相對路徑,可以是文件或目錄的路徑,也可以是一個遠程的文件url;<dest>是容器中的絕對路徑。該命令將復制指定的<src>到容器中的<dest>。其中<src>可以是Dockerfile所在目錄的一個相對路徑(文件或目錄);也可以是一個URL;還可以是一個tar文件(自動解壓為目錄)。
# 如果是一個目錄,那么會將該目錄下的所有文件添加到容器中,不包括目錄;如果文件是可識別的壓縮格式,則docker會幫忙解壓縮(注意壓縮格式);如果<src>是文件且<dest>中不使用斜杠結束,則會將<dest>視為文件,<src>的內容會寫入<dest>;如果<src>是文件且<dest>中使用斜杠結束,則會<src>文件拷貝到<dest>目錄下。
(7)COPY
?? 格式為?? COPY <src> <dest>
?? 復制本地主機的<src>(為Dockerfile所在目錄的相對路徑,文件或目錄)為容器中的<dest>。目標路徑不存在時,會自動創建。
?? 當使用本地目錄為源目錄時,推薦使用COPY。
(8)VOLUME(指定掛載點))
?? 設置指令,使容器中的一個目錄具有持久化存儲數據的功能,該目錄可以被容器本身使用,也可以共享給其他容器使用。我們知道容器使用的是AUFS,這種文件系統不能持久化數據,當容器關閉后,所有的更改都會丟失。當容器中的應用有持久化數據的需求時可以在Dockerfile中使用該指令。格式: VOLUME ["<mountpoint>"]
?? 示例:
?? FROM base?
?? VOLUME ["/tmp/data"]
? ?運行通過該Dockerfile生成image的容器,/tmp/data目錄中的數據在容器關閉后,里面的數據還存在。例如另一個容器也有持久化數據的需求,且想使用上面容器共享的/tmp/data目錄,那么可以運行下面的命令啟動一個容器:
?? docker run -t -i -rm -volumes-from container1 image2 bash?? ##container1為第一個容器的ID,image2為第二個容器運行image的名字。
(9)WORKDIR(切換目錄)
?? 設置指令,可以多次切換(相當于cd命令),對RUN,CMD,ENTRYPOINT生效。格式:
?? WORKDIR /path/to/workdir?
?? 示例:
?? 在 /p1/p2 下執行 vim a.txt?
?? WORKDIR /p1
?? WORKDIR p2
?? RUN vim a.txt?
====================================================================================
(1)httpd的鏡像的創建
?? cd /tmp/docker
?? vim Dockerfile
??? FROM rhel7? ##基礎鏡像
??? ENV HOSTNAME server1
??? EXPOSE 80
??? COPY dvd.repo /etc/yum.repos.d/dvd.repo? ##倉庫沒有yum源,將真機的yum源cp到容器里
??? RUN rpmdb --rebuilddb && yum install -y httpd && yum clean all
??? CMD ["/usr/sbin/httpd","-D","FOREGROUND"]
?? docker build -t rhel7:v1 .?? ##創建鏡像 rhel7:v1
?? docker images
?? docker run -d --name vm1 rhel7:v1
?? docker inspect vm1
?? 測試:在網頁頁面上輸入:172.17.0.2
(2)nginx的原碼編譯的鏡像的創建
?? cd /tmp/docker
?? vim Dockerfile
??? FROM rhel7
??? EXPOSE 80
??? COPY dvd.repo /etc/yum.repos.d/dvd.repo
??? ADD nginx-1.14.0.tar.gz /mnt
??? RUN rpmdb --rebuilddb
??? RUN yum install -y gcc pcre-devel make zlib-devel
??? RUN yum clean all
WORKDIR /mnt/nginx-1.14.0
??? RUN ./configure --prefix=/usr/local/nginx --with-threads --with-file-aio --with-http_stub_status_module
??? RUN make
??? RUN make install
??? CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]
?? docker build -t rhel7:v2 .
?? docker run -d? --name vm2 rhel7:v2
?? docker inspect vm2
?? 測試:在網頁頁面上輸入:172.17.0.2?? (會出現nginx的歡迎界面)
(3)nginx:v1的創建
?? docker load -i distroless-java.tar
?? docker images
?? cd /tmp/docker
?? vim Dockerfile
??? FROM nginx:1.14.1 as base
??? # https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
??? ARG Asia/Shanghai
??? RUN mkdir -p /opt/var/cache/nginx && \
??? ??? cp -a --parents /usr/lib/nginx /opt && \
??? ??? cp -a --parents /usr/share/nginx /opt && \
??? ??? cp -a --parents /var/log/nginx /opt && \
??? ??? cp -aL --parents /var/run /opt && \
??? ??? cp -a --parents /etc/nginx /opt && \
??? ??? cp -a --parents /etc/passwd /opt && \
??? ??? cp -a --parents /etc/group /opt && \
? ? ????cp -a --parents /usr/sbin/nginx /opt && \
??? ??? cp -a --parents /lib/x86_64-linux-gnu/libpcre.so.* /opt && \
??? ??? cp -a --parents /lib/x86_64-linux-gnu/libz.so.* /opt && \
??? ??? cp -a --parents /lib/x86_64-linux-gnu/libc.so.* /opt && \
??? ??? cp -a --parents /lib/x86_64-linux-gnu/libdl.so.* /opt && \
??? ??? cp -a --parents /lib/x86_64-linux-gnu/libpthread.so.* /opt && \
??? ??? cp -a --parents /lib/x86_64-linux-gnu/libcrypt.so.* /opt && \
??? ??? cp -a --parents /usr/lib/x86_64-linux-gnu/libssl.so.* /opt && \
??? ??? cp -a --parents /usr/lib/x86_64-linux-gnu/libcrypto.so.* /opt && \
??? ??? cp /usr/share/zoneinfo/${TIME_ZONE:-ROC} /opt/etc/localtime
??? FROM gcr.io/distroless/base
??? COPY --from=base /opt /
??? EXPOSE 80
??? ENTRYPOINT ["nginx", "-g", "daemon off;"]
?? docker build -t nginx:v1 .
17.縮減鏡像空間
鏡像每一層都有自己的ip,每一層都需要占用一定的空間
優化:--刪除內部的緩存;盡量減少層數;
???? --多級的RUN可以把多個RUN放在一層;
???? --裝了很多的包,安裝完成后,并沒有刪除;
???? --可以在一臺真機上安裝好,再另一個新的倉庫里cp到新的倉庫里;
???? --基礎鏡像的縮減;
18.docker私有倉庫的搭建
私有倉庫的搭建:
?? (1)下載鏡像:docker search registry
?? docker pull registry?? ##或者本機上已經存在registry.tar包,使用docker load? -i registry.tar下載
?? docker images?? ##查看下載后的鏡像
?? (2)鏡像更名:
?? docker tag registry:2.3.1 registry:latest
?? 3運行docker容器:
?? mkdir /tmp/docker/registry? ?##創建數據存儲的文件夾,將真機的/tmp/registry目錄映射到/mnt/docker/registry
?? docker run -d --name registry -p 5000:5000 -v /tmp/docker/registry:/var/lib/registry registry:2.3.1?? ##啟動容器,設定端口5000 ,然后映射文件夾,-v <宿主機目錄>:<容器目錄>
?? (4)推送鏡像到倉庫:
?? docker tag nginx localhost:5000/nginx
?? (5)推送到本地的倉庫上:
?? docker push localhost:5000/nginx?? ##此時可使用tree . 命令查看當前推送結構
?? (6)開放注冊https協議:
?? vim /etc/docker/daemon.json
??? "insecure-registries": ["172.25.254.9:5000"]
?? (7)重啟服務:systemctl restart docker
?? (8)重啟倉庫:docker start registry?? ##此時使用docker ps可以查看到倉庫
?? (9)更名:
?? docker tag rhel7 172.25.254.9:5000/rhel7
?? (10)推送到本地的倉庫上:
?? docker push 172.25.254.9:5000/rhel7
?? (11)查看詳細信息:
?? docker inspect registry:2.3.1?? ##可以看到他的主配置文件在/etc/docker/registry/config.yml
添加證書:
?? (1)生成證書:
?? openssl req \
?? -newkey rsa:4096 -nodes -sha256 -keyout certs/domain.key \
?? -x509 -days 365 -out certs/domain.crt? ##注意主機名必須寫成xx.xx的形式,同時在本機上要做好/etc/hosts的本地解析
?? (2)刪除剛才建好的倉庫:
?? docker rm -f registry
?? (3)建立倉庫:
?? docker run -d --name registry -v `pwd`/certs:/certs -v /tmp/docker/registry:/var/lib/registry -e REGISTRY_HTTP_ADDR=0.0.0.0:443 -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key -p 443:443 registry:2.3.1?? ##其中:-e REGISTRY_HTTP_ADDR=0.0.0.0:443 編輯容器內部參數? ?-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt 使用證書?? -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key 私鑰?? -p 443:443 端口映射
?? (4)添加認證:
?? mkdir /etc/docker/certs.d
?? mkdir /etc/docker/certs.d/westos.org
?? cd /etc/docker/certs.d/westos.org
?? cp /tmp/docker/certs/domain.crt ca.crt
?? (5)更名:
?? docker tag ubuntu:latest westos.org/ubuntu
?? (6)推送到本地的倉庫上:
?? docker push westos.org/ubuntu
添加用戶認證:
?? (1)添加用戶:
?? docker run --rm --entrypoint htpasswd registry:2.3.1 -Bbn admin westos > auth/htpasswd
?? 追加用戶:
?? docker run --rm --entrypoint htpasswd registry:2.3.1 -Bbn wf westos >> auth/htpasswd
?? (2)刪除剛才建好的倉庫:
?? docker rm -f registry
?? (3)建立倉庫:
?? docker run -d --name registry -v `pwd`/certs:/certs -v /tmp/docker/registry:/var/lib/registry -e REGISTRY_HTTP_ADDR=0.0.0.0:443 -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key -v `pwd`/auth:/auth -e REGISTRY_AUTH=htpasswd -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd -p 443:443 registry:2.3.1
?? (4)更名:
?? docker tag game2048:latest westos.org/
?? (5)用戶登陸:
??? docker login westos.org?? ##一定要先成功登陸以后才能推送
?? (6)推送到本地的倉庫上:
?? docker push westos.org/game2048
19.docker-compose
?? Docker Compose 是一個用來創建和運行多容器應用的工具。使用 Compose首先需要編寫Compose 文件來描述多個容器服務以及之間的關聯,然后通過命令根據配置啟動所有的容器。Dockerfile 可以定義一個容器,而一個 Compose 的模板文件(YAML 格式)可以定義一個包含多個相互關聯容器的應用。
?? docker load -i haproxy.tar
?? cp docker-compose-Linux-x86_64-1.22.0 /usr/local/bin/docker-compose
?? chmod +x/usr/local/bin/docker-compose
? ?cd /tmp/docker/
?? mkdir compose
?? cd compose/
?? vim docker-compose.yml
?? mkdir haproxy
?? cd haproxy/
?? vim haproxy.cfg
?? docker-compose up?? ##可能會啟動不了,報錯顯示,端口被占用
?? systemctl stop httpd?? ##可能是http服務占用了80端口,將服務關閉
?? docker-compose up?? ##再次開啟就會起來
?? 重起一個shell:
?? docker ps?? ##就可以看到compose運行
?? cd /tmp/docker/web
?? vim index.html
??? wf
?? docker cp index.html compose_web1_1:/usr/share/html
?? vim index.html
??????? westos
?? docker cp index.html compose_web2_1:/usr/share/html
?? 測試: 在網頁上就可以看到負載均衡的結果
?? 注意:如果要開啟/關閉 compose ,必須要在compose的目錄下,因為它會要讀取yml文件,不在目錄下開啟/關閉,會發生報錯
?
轉載于:https://www.cnblogs.com/wf-aiyouwei/p/10003930.html
總結
以上是生活随笔為你收集整理的企业——Docker容器的搭建及简单应用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 什么是道德?
- 下一篇: Postman----Presets(预