主頁 >  其他 > Docker從入門到初步掌握

Docker從入門到初步掌握

2021-10-19 08:20:12 其他

提綱:Docker和Kubernetes關系

zheg

本人開始今天分享之前想提以前簡單的問題,大家可以試試回答,Kubernetes和Docker關系?

Kubernetes的作用是管理容器,docker一旦變多,重啟,容器通信等一系列程序就需要一個工具來進行管理,這就是Kubernetes做的事情

在這里插入圖片描述

K8S 調度的基本單位為 pod(一個POD表示一個或多個容器),為什么基本單位不是一個容器?

Docker概述

Docker是什么?

? Docker 是一個開源專案,誕生于 2013 年初,最初是 dotCloud 公司內部的一個業余專案,它基于 Google 公司推出的Go語言實作,專案后來加入了 Linux 基金會,遵從了 Apache 2.0 協議,專案代碼在GitHub 上進行維護,

? Docker 專案的目標是實作輕量級的作業系統虛擬化解決方案,Docker 的基礎是 Linux 容器(LXC)等技術,在 LXC 的基礎上 Docker 進行了進一步的封裝,讓用戶不需要去關心容器的管理,使得操作更為簡便,用戶操作 Docker 的容器就像操作一個快速輕量級的虛擬機一樣簡單,

既然是都是虛擬化技術, 為什么不直接使用虛擬機?

序號Docker虛擬機
1占用資源少資源占用多
2操作簡單冗余步驟多
3啟動快啟動慢

備注:區分容器和虛擬機概念(容器起源自Linux Containers(LXC)一種新的虛擬化技術)

  • 容器內應用行程直接運行于宿主內核是對行程進行隔離的技術、包含完整檔案系統,并區分計算資源、自身無內核、無需硬體虛擬,

  • 虛擬機在虛擬出一套硬體后在其基礎上搭建套作業系統,后運行軟體,

(補充)為什么Docker比較 VM 快?

1、docker有著比虛擬機更少的抽象層,由亍docker不需要Hypervisor實作硬體資源虛擬化,運行在docker容器上的程式直接使用的都是實際物理機的硬體資源,因此在CPU、記憶體利用率上docker將會在效率上有明顯優勢,

2 、docker利用的是宿主機的內核,而不需要Guest OS,因此,當新建一個容器時,docker不需要和虛擬機一樣重新加載一個作業系統內核,仍而避免引尋、加載作業系統內核返個比較費時費資源的程序,當新建一個虛擬機時,虛擬機軟體需要加載Guest OS,返個新建程序是分鐘級別的,而docker由于直接利用宿主機的作業系統,則省略了返個程序,因此新建一個docker容器只需要幾秒鐘,

容器化技術給開發/運維(DevOps)/部署能帶來哪些便捷?

序號維度Docker開發/運維傳統開發/運維
1應用交付和部署少量容器鏡像檔案(組態檔內置)復雜的安裝程式和配置說明檔案
2升級、遷移、擴縮容通過鏡像運行新的容器進行快速擴容重新部署上線
3系統運維生產、開發、測驗環境高度一致;
組態檔封裝;
測驗快速定位、修復;
更快速的交付和部署;
更簡單的管理;
更快速的啟動時間
生產、開發、測驗環境高不一致;
管理、交付、部署難度大;
虛擬機啟動時間慢
4資源利用內核級虛擬化;
一臺物理機上可以運行很多個容器實體;
提升物理服務器的CPU和記憶體的利用率;
傳統的虛擬化技術需要額外Hypervisor

Docker是怎么作業的?

Docker是一個Client-Server結構的系統,Docker守護行程運行在主機上, 然后通過Socket連接從客戶端訪問,守護行程從客戶端接受命令并管理運行在主機上的容器, 容器,是一個運行時環境,就是我們 前面說到的集裝箱,

備注:

  • Docker官網:http://www.docker.com
  • Docker中文網站:https://www.docker-cn.com
  • Docker Hub官網:https://hub.docker.com (倉庫)

?

Docker安裝

Docker組成

在這里插入圖片描述

備注:區分鏡像和容器

  • 鏡像(image):Docker 鏡像(Image)就是一個只讀的模板,鏡像可以用來創建 Docker 容器,一個鏡像可以創建很多容器, 就好似 Java 中的 類和物件,類就是鏡像,容器就是物件!

  • 容器(container):Docker 利用容器(Container)獨立運行的一個或一組應用,容器是用鏡像創建的運行實體, 它可以被啟動、開始、停止、洗掉,每個容器都是相互隔離的,保證安全的平臺,可以把容器看做是一個簡易版的 Linux 環境(包括root用戶權限、行程空間、用戶空間和網路空間等) 和運行在其中的應用程式,

  • 倉庫(repository):倉庫(Repository)是集中存放鏡像檔案的場所, 倉庫(Repository)和倉庫注冊服務器(Registry)是有區別的,倉庫注冊服務器上往往存放著多個倉庫,每個倉庫中又包含了多個鏡像,每個鏡像有不同的標簽(tag), 倉庫分為公開倉庫(Public)和私有倉庫(Private)兩種形式,最大的公開倉庫是 Docker Hub(https://hub.docker.com/),存放了數量龐大的鏡像供用戶下載, 國內的公開倉庫包括阿里云 、網易云等

補充:容器的定義和鏡像幾乎一模一樣,也是一堆層的統一視角,唯一區別在于容器的最上面那一層是可讀可寫的,

Docker安裝

官網安裝參考手冊:https://docs.docker.com/engine/install/centos/

1、yum安裝gcc相關環境(需要確保 虛擬機可以上外網 )

yum -y install gcc
yum -y install gcc-c++

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

4、設定鏡像倉庫

# 正確推薦使用國內的
yum-config-manager --add-repo http://mirrors.aliyun.com/docker- ce/linux/centos/docker-ce.repo

5、更新yum軟體包索引

yum makecache fast

6、安裝 Docker CE

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

7、啟動Docker

systemctl start docker

8、卸載Docker

systemctl stop docker
yum -y remove docker-ce docker-ce-cli containerd.io
rm -rf /var/lib/docker

Docker常用命令

基本命令

docker version 				# 顯示 Docker 版本資訊,
docker info  				# 顯示 Docker 系統資訊,包括鏡像和容器數,,
docker --help 				# 幫助
docker images 				# 列出本地主機上的鏡像
# 備注:同一個倉庫源可以有多個 TAG,代表這個倉庫源的不同版本,我們使用REPOSITORY:TAG 定義不同 的鏡像,如果你不定義鏡像的標簽版本,docker將默認使用 lastest 鏡像!

docker search mysql 		# 搜索鏡像
docker pull mysql/mysql:8.0			# 下載鏡像
docker pull centos					 # 下載容器

docker rmi -f 鏡像id					 # 洗掉單個
docker rmi -f 鏡像名:tag 鏡像名:tag 	 # 洗掉多個 
docker rmi -f $(docker images -qa)   # 洗掉全部


docker run -it centos /bin/bash		# 新建容器并啟動
docker ps							  # 列出所有運行的容器

docker start (容器id or 容器名) 		# 啟動容器
docker restart (容器id or 容器名)	# 重啟容器
docker stop (容器id or 容器名) 		# 停止容器
docker kill (容器id or 容器名)		# 強制停止容器

docker rm 容器id 						# 洗掉指定容器 
docker rm -f $(docker ps -a -q) 	# 洗掉所有容器 
docker ps -a -q|xargs docker rm 	# 洗掉所有容器

# 從容器內拷貝檔案到主機上
docker cp 容器id:容器內路徑 目的主機路徑

docker commit 提交容器副本使之成為一個新的鏡像!
# 語法
docker commit -m="提交的描述資訊" -a="作者" 容器id 要創建的目標鏡像名:[標簽名]

# 例子
docker run -d centos 	# 啟動centos,使用后臺方式啟動
docker inspect 容器id

# 語法:
# -d 	后臺運行 
# -p 	埠 
# -v 	容器資料卷
# -i	以互動模式運行容器,通常與 -t 同時使用
# -t	為容器重新分配一個偽輸入終端,通常與 -i 同時使用
# -d	后臺運行容器,并回傳容器ID
# -itd 	組合命

# 容器進入:
docker exec -it --user root docker-nginx /bin/bash

# 檔案向容器復制:
# 語法:docker cp 容器外路徑 容器ID:容器內路徑
docker cp 外部檔案地址 e7f25fc3bd48:容器內檔案地址

# Nginx:
docker run -d -p 80:80 -v 外部檔案地:容器內檔案地址 --name docker-nginx nginx

# MySQL:
docker run -d -p 3306:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name docker-mysql mysql:8.0

# Redis:
docker run -itd --name docker-redis -p 6379:6379 redis

# RabbitMQ:
docker pull rabbitmq 
docker pull rabbitmq:management
docker run -d --name docker-rabbitmq -p 5671:5671 -p 5672:5672 -p 4369:4369 -p 25672:25672 -p 15671:15671 -p 15672:15672 rabbitmq:management

練習:

docker search nginx
docker pull nginx
docker images
docker run -d --name mynginx -p 3500:80 nginx
docker ps
curl localhost:3500

docker exec -it mynginx /bin/bash
whereis nginx # 尋找nginx
cd /usr/share/nginx # nginx 的路徑
vim  index.html #修改index

可視化/管理工具

在這里插入圖片描述

Portainer

docker run -d -p 8088:9000 \
--restart=always -v /var/run/docker.sock:/var/run/docker.sock --
privileged=true portainer/portainer

Portainer是Docker的圖形化管理工具,提供狀態顯示面板、應用模板快速部署、容器鏡像網路資料卷的基本操作(包括上傳下載鏡像,創建容器等操作)、事件日志顯示、容器控制臺操作、Swarm集群和服務等集中管理和操作、登錄用戶管理和控制等功能,功能十分全面,面向中小型單位對容器管理的全部需求,

訪問方式:http://IP:8088

首次登陸需要注冊用戶,給admin用戶設定密碼:單機版這里選擇local即可,選擇完畢,點擊Connect即可連接到本地docker:

Docker Dasktop

在這里插入圖片描述

Docker鏡像原理

鏡像是什么?

鏡像是一種輕量級、可執行的獨立軟體包,用來打包軟體運行環境和基于運行環境開發的軟體,它包含運行某個軟體所需的所有內容,包括代碼、運行時、庫、環境變數和組態檔,

Docker鏡像加載原理

在聊這個話題時候需要提前了解兩個知識點,什么是UnionFS ?有興趣可以去了解一下,這里只做簡單闡述,

? UnionFS(聯合檔案系統):Union檔案系統(UnionFS)是一種分層、輕量級并且高性能的檔案系統,它支持對檔案系統的修改作為一次提交來一層層的疊加,同時可以將不同目錄掛載到同一個虛擬檔案系統下(unite several directories into a single virtual filesystem),Union 檔案系統是 Docker 鏡像的基礎,鏡像可以通過分層來進行繼承,基于基礎鏡像(沒有父鏡像),可以制作各種具體的應用鏡像,

特性:一次同時加載多個檔案系統,但從外面看起來,只能看到一個檔案系統,聯合加載會把各層檔案系統疊加起來,這樣最終的檔案系統會包含所有底層的檔案和目錄

UnionFS和Docker鏡像加載原理有什么關系?

在這里插入圖片描述

docker的鏡像實際上由一層一層的檔案系統組成,這種層級的檔案系統UnionFS,bootfs(boot file system)主要包含bootloader和kernel, bootloader主要是引導加載kernel, Linux剛啟動時會加載bootfs檔案系統,在Docker鏡像的最底層是bootfs,這一層與我們典型的Linux/Unix系統是一樣的,包含boot加載器和內核,當boot加載完成之后整個內核就都在記憶體中了,此時記憶體的使用權已由bootfs轉交給內核,此時系統也會卸載bootfs,bootfs (root file system) ,在bootfs之上,包含的就是典型 Linux 系統中的 /dev, /proc, /bin, /etc 等標準目錄和檔案,rootfs就是各種不同的作業系統發行版,比如Ubuntu,Centos等等,

平時我們安裝進虛擬機的CentOS都是好幾個G,為什么Docker這里才200M?

對于一個精簡的OS,rootfs 可以很小,只需要包含最基本的命令,工具和程式庫就可以了,因為底層直接用Host的kernel,自己只需要提供rootfs就可以了,由此可見對于不同的linux發行版, bootfs基本是一致的, rootfs會有差別, 因此不同的發行版可以公用bootfs,

備注: Linuxkernel是一個一體化內核(monolithic kernel)系統,提供硬體抽象層、磁盤及檔案系統控制、多任務等功能的系統軟體,不是一套完整的作業系統,有興趣可以去閱讀: Linux內核的作業原理

Docker檔案分層原理

分層的鏡像:我們可以去下載一個鏡像,注意觀察下載的日志輸出,可以看到是一層一層的在下載!

在這里插入圖片描述

為什么Docker鏡像要采用這種分層的結構呢?

最大的好處,我覺得莫過于是資源共享了!比如有多個鏡像都從相同的Base鏡像構建而來,那么宿主機只需在磁盤上保留一份base鏡像,同時記憶體中也只需要加載一份base鏡像,這樣就可以為所有的容器服務了,而且鏡像的每一層都可以被共享,

備注:查看鏡像分層的方式可以通過 docker image inspect 命令!

拓展:所有的 Docker 鏡像都起始于一個基礎鏡像層,當進行修改或增加新的內容時,就會在當前鏡像層上,創建新的鏡像層,舉一個簡單的例子,假如基于 Ubuntu Linux 16.04 創建一個新的鏡像,這就是新鏡像的第一層;如果在該鏡像中添加 Python包,就會在基礎鏡像層之上創建第二個鏡像層;如果繼續添加一個安全補丁,就會創建第三個鏡像層,該鏡像當前已經包含 3 個鏡像層,如下圖所示(這只是一個用于演示的很簡單的例子),

在添加額外的鏡像層的同時,鏡像始終保持是當前所有鏡像的組合,理解這一點非常重要,下圖中舉了一個簡單的例子,每個鏡像層包含 3 個檔案,而鏡像包含了來自兩個鏡像層的 6 個檔案,

在這里插入圖片描述

上圖中的鏡像層跟之前圖中的略有區別,主要目的是便于展示檔案,下圖中展示了一個稍微復雜的三層鏡像,在外部看來整個鏡像只有 6 個檔案,這是因為最上層中的檔案7 是檔案 5 的一個更新版本,這種情況下,上層鏡像層中的檔案覆寫了底層鏡像層中的檔案,這樣就使得檔案的更新版本作為一個新鏡像層添加到鏡像當中,

Docker 通過存盤引擎(新版本采用快斬訓制)的方式來實作鏡像層堆疊,并保證多鏡像層對外展示為統一的檔案系統,

Linux 上可用的存盤引擎有 AUFS、Overlay2、Device Mapper、Btrfs 以及 ZFS,顧名思義,每種存盤引擎都基于 Linux 中對應的檔案系統或者塊設備技術,并且每種存盤引擎都有其獨有的性能特點,

Docker 在 Windows 上僅支持 windowsfilter 一種存盤引擎,該引擎基于 NTFS 檔案系統之上實作了分層和 CoW[1],下圖展示了與系統顯示相同的三層鏡像,所有鏡像層堆疊并合并,對外提供統一的視圖,

(img-GW34mpWa-1634551438154)(https://i.loli.net/2021/08/30/NVgljJnYWadeCqD.png)]https://i.loli.net/2021/08/30/NVgljJnYWadeCqD.png

特點:Docker鏡像都是只讀的,當容器啟動時,一個新的可寫層被加載到鏡像的頂部!這一層就是我們通常說的容器層,容器之下的都叫鏡像層!

Docker資料持久

容器資料卷

什么是容器資料卷,為什么要用容器資料卷?

將應用和運行的環境打包形成容器運行,運行可以伴隨著容器,但是我們對于資料的要求,是希望能夠持久化的!就好比,你安裝一個MySQL,結果你把容器刪了,就相當于刪庫跑路了,這TM也太扯了吧!所以我們希望容器之間有可能可以共享資料,Docker容器產生的資料,如果不通過docker commit 生成新的鏡像,使得資料作為鏡像的一部分保存下來,那么當容器洗掉后,資料自然也就沒有了!這樣是行不通的!為了能保存資料在Docker中我們就可以使用卷!讓資料掛載到我們本地!這樣資料就不會因為容器洗掉而丟失了!

容器資料卷作用是什么?

卷就是目錄或者檔案,存在一個或者多個容器中,由docker掛載到容器,但不屬于聯合檔案系統,因此能夠繞過 Union File System , 提供一些用于持續存盤或共享資料的特性:卷的設計目的就是資料的持久化,完全獨立于容器的生存周期,因此Docker不會在容器洗掉時洗掉其掛載的資料卷,

容器資料卷特點?

  • 資料卷可在容器之間共享或重用資料
  • 卷中的更改可以直接生效
  • 資料卷中的更改不會包含在鏡像的更新中
  • 資料卷的生命周期一直持續到沒有容器使用它為止

備注:總結一句話: 就是容器的持久化,以及容器間的繼承和資料共享!

容器資料卷如何使用?

docker run -it -v 宿主機絕對路徑目錄:容器內目錄 鏡像名
# 測驗
[root@kuangshen ~]# docker run -it -v /home/ceshi:/home centos /bin/bash

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-f8SWyTLg-1634551438155)(https://i.loli.net/2021/08/30/qnVfBJiOzKskuav.png)]

容器掛載

mysql 資料持久化的問題!

# 1、搜索鏡像
[root@kuangshen ~]# docker search mysql
NAME DESCRIPTION
STARS
mysql MySQL is a widely used, open-source
relation... 9488

# 2、拉取鏡像
[root@kuangshen ~]# docker pull mysql:5.7
5 .7: Pulling from library/mysql
54fec2fa59d0: Already exists
bcc6c6145912: Pull complete
951c3d959c9d: Pull complete
05de4d0e206e: Pull complete
319f0394ef42: Pull complete
d9185034607b: Pull complete
013a9c64dadc: Pull complete
e745b3361626: Pull complete
03145d87b451: Pull complete
3991a6b182ee: Pull complete
62335de06f7d: Pull complete
Digest:
sha256:e821ca8cc7a44d354486f30c6a193ec6b70a4eed8c8362aeede4e9b8d74b8ebb
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7


# 3、啟動容器 -e 環境變數!
# 注意: mysql的資料應該不丟失!先體驗下 -v 掛載卷! 參考官方檔案
[root@kuangshen home]# docker run -d -p 3310:3306 -v
/home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e
MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
4763fa5c68c4323688102f57938fb10996a0fb902d2812349286529f9378f16c


# 4、使用本地的sqlyog連接測驗一下 3310

# 5、查看本地的 /home/mysql 目錄 [root@kuangshen data]# pwd /home/mysql/data [root@kuangshen data]# ls
.. ... . test # 可以看到我們剛剛建立的mysql資料庫在本地存盤著


# 6、洗掉mysql容器
[root@kuangshen data]# docker rm -f mysql01 # 洗掉容器,然后發現遠程連接失敗! mysql01
[root@kuangshen data]# ls
.. ... . test # 可以看到我們剛剛建立的mysql資料庫在本地存盤著

匿/具名掛載

什么是匿名和具名掛載?

# 匿名掛載
-v 容器內路徑
docker run -d -P --name nginx01 -v /etc/nginx nginx
# 匿名掛載的缺點,就是不好維護,通常使用命令 docker volume維護 docker volume ls
# 具名掛載
-v 卷名:/容器內路徑
docker run -d -P --name nginx02 -v nginxconfig:/etc/nginx nginx
# 查看掛載的路徑
[root@kuangshen ~]# docker volume inspect nginxconfig [
    {
        "CreatedAt": "2020-05-13T17:23:00+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/nginxconfig/_data",
        "Name": "nginxconfig",
        "Options": null,
        "Scope": "local"
} ]
# 怎么判斷掛載的是卷名而不是本機目錄名? 不是/開始就是卷名,是/開始就是目錄名
# 改變檔案的讀寫權限
# ro: readonly
# rw: readwrite
# 指定容器對我們掛載出來的內容的讀寫權限
docker run -d -P --name nginx02 -v nginxconfig:/etc/nginx:ro nginx docker run -d -P --name nginx02 -v nginxconfig:/etc/nginx:rw nginx

Docker File

DockerFile 是用來構建Docker鏡像的構建檔案,是由一些列命令和引數構成的腳本,我們在這里,先體驗下,后面我們會詳細講解 DockerFile !

測驗:

# 1、我們在宿主機 /home 目錄下新建一個 docker-test-volume檔案夾
[root@kuangshen home]# mkdir docker-test-volume

# 說明:在撰寫DockerFile檔案中使用 VOLUME 指令來給鏡像添加一個或多個資料卷 
VOLUME["/dataVolumeContainer1","/dataVolumeContainer2","/dataVolumeContainer 3"]

# 出于可移植和分享的考慮,我們之前使用的 -v 主機目錄:容器目錄 這種方式不能夠直接在 DockerFile中實作,
# 由于宿主機目錄是依賴于特定宿主機的,并不能夠保證在所有宿主機上都存在這樣的特定目錄.

# 2、撰寫DockerFile檔案
[root@kuangshen docker-test-volume]# pwd /home/docker-test-volume
[root@kuangshen docker-test-volume]# vim dockerfile1 [root@kuangshen docker-test-volume]# cat dockerfile1
# volume test
FROM centos
VOLUME ["/dataVolumeContainer1","/dataVolumeContainer2"] CMD echo "-------end------"
CMD /bin/bash

# 3、build后生成鏡像,獲得一個新鏡像 kuangshen/centos
docker build -f /home/docker-test-volume/dockerfile1 -t kuangshen/centos . # 注意最后有個.

# 4、啟動容器
[root@kuangshen docker-test-volume]# docker run -it 0e97e1891a3d /bin/bash # 啟動容器
[root@f5824970eefc /]# ls -l
total 56
# 問題:通過上述步驟,容器內的卷目錄地址就已經知道了,但是對應的主機目錄地址在哪里呢?


# 5、我們在資料卷中新建一個檔案
[root@f5824970eefc dataVolumeContainer1]# pwd /dataVolumeContainer1
[root@f5824970eefc dataVolumeContainer1]# touch container.txt [root@f5824970eefc dataVolumeContainer1]# ls -l
total 0
-rw-r--r-- 1 root root 0 May 11 11:58 container.txt


# 6、查看下這個容器的資訊
[root@kuangshen ~]# docker inspect 0e97e1891a3d # 查看輸出的Volumes
"Volumes": {
    "/dataVolumeContainer1": {},
    "/dataVolumeContainer2": {}
},

# 7、這個卷在主機對應的默認位置

# 注意:如果訪問出現了 cannot open directory: Permission denied 解決辦法:在掛載目錄后多加一個 --privileged=true引數即可

資料卷容器

有人會問資料卷容器和容器資料卷有什么區別?

? 它們都是一種同步、持久化技術,容器資料卷是為了防止洗掉容器的時候資料丟失,構建起鏡像和外部檔案系統同步機制;資料卷容器是其他的容器通過掛載這個父容器實作資料共享,掛載資料卷的容器,是容器之間資料共享同步機制(類似于單專案集群思想),

在這里插入圖片描述

資料卷容器如何使用?

我們使用上一步的鏡像:kuangshen/centos 為模板,運行容器 docker01,docker02,docker03,他們都會具有容器卷,我們來測試下,容器間傳遞共享

docker run -it - -name parentContainer  鏡像名 	#建立父容器

#語法:--volumes-from
docker run -it - -name sonContainer1 --volumes -from parentContainer 鏡像名
docker run -it - -name sonContainer2 --volumes -from parentContainer 鏡像名

結論:容器之間配置資訊的傳遞,資料卷的生命周期一直持續到沒有容器使用它為止,存盤在本機的檔案則會一直保留!

DockerFile

DockerFile基礎

大家想想,Nginx,tomcat,mysql 這些鏡像都是哪里來的?官方能寫,我們不能寫嗎?如何實作自己的docker鏡像,么就需要用到DockerFile

  • 微服務單體springboot應用打包成鏡像(包含資料庫、APP、訊息佇列…)

  • 流程:開發應用=>DockerFile=>打包為鏡像=>上傳到倉庫(私有倉庫,公有倉庫)=> 下載鏡像 => 啟動

什么是DockerFile?

DockerFile是用來構建Docker鏡像的構建檔案,是由一系列命令和引數構成的腳本,

如何實作一個dockerFile?

基礎知識:

FROM 		# 基礎鏡像,當前新鏡像是基于哪個鏡像的 MAINTAINER # 鏡像維護者的姓名混合郵箱地址
RUN 		# 容器構建時需要運行的命令
EXPOSE 		# 當前容器對外保留出的埠
WORKDIR 	# 指定在創建容器后,終端默認登錄的進來作業目錄,一個落腳點
ENV 		# 用來在構建鏡像程序中設定環境變數
ADD			# 將宿主機目錄下的檔案拷貝進鏡像且ADD命令會自動處理URL和解壓tar壓縮包 COPY # 類似ADD,拷貝檔案和目錄到鏡像中!
VOLUME 		# 容器資料卷,用于資料保存和持久化作業
CMD 		# 指定一個容器啟動時要運行的命令,dockerFile中可以有多個CMD指令,但只有最 后一個生效!
ENTRYPOINT 	# 指定一個容器啟動時要運行的命令!和CMD一樣
ONBUILD 	# 當構建一個被繼承的DockerFile時運行命令,父鏡像在被子鏡像繼承后,父鏡像的 ONBUILD被觸發

DockerFile測驗

建構步驟:撰寫DockerFile檔案>docker build 構建鏡像>docker run

例子地址:https://hub.docker.com/_/centos

創建app.py

#ipython
#ipython os
#mkdir python_app
#cd python_app
#vim app.py:
from flask import Flask             	  	#from模塊呼叫
import socket                            	#為了獲取主機名稱用
import os                                	#獲取環境變數用的
 
app = Flask(__name__)                         
 
@app.route('/')                             
def hello():
    html = "Hello {name} Hostname: {hostname} This is Dockerfile Demo"
    return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname())  
    
if __name__ == "__main__":           #主函式
    app.run(host='0.0.0.0', port=80)     #監控本地所有的網卡、監控80埠

創建requirements.txt

Flask

創建Dockerfile

FROM python:3.7-alpine
WORKDIR /app
ADD . /app
RUN pip install --trusted-host pypi.python.org -r requirements.txt
# 使用 pip 命令安裝這個應用所需要的依賴
EXPOSE 80
# 允許外界訪問容器的 80 埠
ENV NAME World
# 設定環境變數
CMD ["python", "app.py"]

DockerFile拓展

除上述的功能點以外Dockerfile還提供了HEALTHCHECK(狀態服務監控)、ENV/ARG(環境配置)、ENTRYPOINT(入口指令)等功能,有興趣的小伙伴可以去研究一下,

Docker Compose

什么是Docker Compose?

? Compose 是用于定義和運行多容器 Docker 應用程式的工具,通過 Compose,您可以使用 **YML **檔案來配置應用程式需要的所有服務,然后,使用一個命令,就可以從 YML 檔案配置中創建并啟動所有服務,

Docker Compose安裝

安裝地址:https://docs.docker.com/compose/install/

 sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
#備注:要安裝其他版本的 Compose,請替換 1.24.1,


# 將可執行權限應用于二進制檔案:
sudo chmod +x /usr/local/bin/docker-compose


# 創建軟鏈:
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose


# 測驗是否安裝成功:
docker-compose --version
#輸出:cker-compose version 1.24.1, build 4667896b

# 卸載
sudo rm /usr/local/bin/docker-compose
pip uninstall docker-compose

Docker Compose測驗

mkdir composetest
cd composetest

建一個py.app檔案

import time
 
import redis
from flask import Flask
app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)
def get_hit_count():
    retries = 5
    while True:
        try:
            return cache.incr('hits')
        except redis.exceptions.ConnectionError as exc:
            if retries == 0:
                raise exc
            retries -= 1
            time.sleep(0.5)
@app.route('/')
def hello():
    count = get_hit_count()
    return 'Hello World! I have been seen {} times.\n'.format(count)
 
if __name__ == "__main__":
    app.run(host="0.0.0.0", debug=True)

創建一個txt檔案requirements.txt

flask
redis

創建一個Dockerfile

FROM python:3.4-alpine
ADD . /code
WORKDIR /code
RUN pip install -r requirements.txt
CMD ["python", "app.py"]

創建 docker-compose.yml

# yaml 配置
version: '3'
services:
  web:
    build: .
    ports:
     - "8848:8848"
  redis:
    image: "redis:alpine"

專案構建

# 啟動應用程式:
docker-compose up

#后臺執行該服務可以加上 -d 引數:
docker-compose up -d

Docker Compose拓展

除了上面常見的配置,Docker Compose yaml 配置還提供了 endpoint_mode(集群模式vip和輪詢機制dnsrr)、healthcheck、logging、network_mode、restart、secrets(存盤敏感資料)、devices、dns、env_file、extra_hosts(主機映射)…等等,大家有興趣的可以去研究一下,

Docker 網路講解

在這里插入圖片描述

Docker容器互聯

Docker0(IP)

在這里插入圖片描述

問題:什么是Docker0?

? Docker啟動的時候會在主機上自動創建一個docker0網橋,實際上是一個Linux網橋,所有容器的啟動如果在docker run的時候沒有指定網路模式的情況下都會掛載到docker0網橋上,這樣容器就可以和主機甚至是其他容器之間通訊了,

docker network ls					  # Docker網路(bridge:橋接模式 host:主機模式 none:無網路模式)
docker rm -f $(docker ps -a -q) 	# 洗掉所有容器
docker rmi -f $(docker images -qa) 	# 洗掉全部鏡像

問題:Docker 是如何處理容器網路訪問的?

每一個安裝了Docker的linux主機都有一個docker0的虛擬網卡,這是個橋接網卡,使用了veth-pair技術!

小結:

Docker使用Linux橋接,在宿主機虛擬一個Docker容器網橋(docker0),Docker啟動一個容器時會根據Docker網橋的網段分配給容器一個IP地址,稱為Container-IP,同時Docker網橋是每個容器的默認網關,因為在同一宿主機內的容器都接入同一個網橋,這樣容器之間就能夠通過容器的Container-IP直接通信,

Docker容器網路就很好的利用了Linux虛擬網路技術,在本地主機和容器內分別創建一個虛擬介面,并讓他們彼此聯通(這樣一對介面叫veth pair);Docker中的網路介面默認都是虛擬的介面,虛擬介面的優勢就是轉發效率極高(因為Linux是在內核中進行資料的復制來實作虛擬介面之間的資料轉發,無需通過外部的網路設備交換),對于本地系統和容器系統來說,虛擬介面跟一個正常的以太網卡相比并沒有區別,只是他的速度快很多,

Docker–Link(容器名)

??思考一個場景,我們撰寫一個微服務,資料庫連接地址原來是使用ip的,如果ip變化就不行了,那我們能不能使用服務名訪問呢?jdbc:mysql://mysql:3306,這樣的話哪怕mysql重啟,我們也不需要修改配置了!docker提供了 --link的操作!

docker run --name mysql --restart=always  -d  -e MYSQL_ROOT_PASSWORD=123456 mysql:5.6
docker run -d --name  接收容器名(#一般是tomcat) --link 源容器(被連接容器)(#一般是mysql) --restart=always  源容器鏡像名
     	
docker run -d -p 8080:8080 --name tomcat --link mysql --restart=always -v /data/tomcat/webapps:/usr/local/tomcat/webapps tomcat

備注:–link早都過時了,我們不推薦使用!我們可以使用自定義網路的方式

自定義網路

在這里插入圖片描述

# 命令
[root@kuangshen ~]# docker network inspect 4eb2182ac4b2 [
    {
        "Name": "bridge",
        "Id":
"4eb2182ac4b23487e1eb6e06df56c71ab6f0adc7ccc0962b4747d0eed5ad6690",
        "Created": "2020-05-11T15:44:20.131441544+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
{
// 默認docker0是管理這個子網范圍內的,0~16,也就是 255*255,去掉0個255,我們有65534可以分配的ip
// docker0網路默認可以支持創建6萬多個容器ip不重復
] },
    "Subnet": "172.18.0.0/16",
    "Gateway": "172.18.0.1"
}
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
    "Network": ""
},
"ConfigOnly": false,
"Containers": {
 "a3a4a17a2b707766ad4f2bb967ce1d94f658cd4cccef3bb8707395cdc71fa1e7": {
                "Name": "tomcat03",
                "EndpointID":
"5fe62d0be3a1343aa74f6bb77885d3657b191210cafad200e5054e1bdfe56be9",
                "MacAddress": "02:42:ac:12:00:04",
                "IPv4Address": "172.18.0.4/16",
                "IPv6Address": ""
},
 "b80da266a3ad85fcc874c5f0d3c897246ebc40533cb745bb24180237cc3167b1": {
                "Name": "tomcat02",
                "EndpointID":
"6232cac0c4e7fed30c9fa5eebc9238f9fc44f548f257344b5440d6d486825256",
                "MacAddress": "02:42:ac:12:00:03",
                "IPv4Address": "172.18.0.3/16",
                "IPv6Address": ""
},
 "f38239e2b405bccf8c93bd1052f336f661033b9b27ef9b3f99a018c108e06f87": {
                "Name": "tomcat01",
                "EndpointID":
"31dc174b8f3f15f217acdc3ac7e8a235a03d59438f863706c0143b4426772c5e",
                "MacAddress": "02:42:ac:12:00:02",
                "IPv4Address": "172.18.0.2/16",
                "IPv6Address": ""
} },
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
},
        "Labels": {}
    }
]
# 默認我們不配置網路,也就相當于默認值 --net bridge 使用的docker0 
docker run -d -P --name tomcat01 --net bridge tomcat
# docker0網路的特點 
1.它是默認的
2.域名訪問不通
3.--link 域名通了,但是刪了又不行

備注:聊了這么多,我們現在應該可以深刻理解docker的網路了!

實戰:部署Redis集群

# 創建網卡
docker network create redis --subnet 172.38.0.0/16
# 通過腳本創建六個redis配置
for port in $(seq 1 6); \
do \
mkdir -p /mydata/redis/node-${port}/conf
touch /mydata/redis/node-${port}/conf/redis.conf
cat << EOF >/mydata/redis/node-${port}/conf/redis.conf port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.38.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done
docker run -p 637${port}:6379 -p 1637${port}:16379 --name redis-${port} \
-v /mydata/redis/node-${port}/data:/data \
-v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.1${port} redis:5.0.9-alpine3.11 redis-server
/etc/redis/redis.conf; \
# 啟動6個容器
docker run -p 6371:6379 -p 16371:16379 --name redis-1 \
-v /mydata/redis/node-1/data:/data \
-v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
docker run -p 6376:6379 -p 16376:16379 --name redis-6 \
-v /mydata/redis/node-6/data:/data \
-v /mydata/redis/node-6/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.16 redis:5.0.9-alpine3.11 redis-server
/etc/redis/redis.conf
# 進入一個redis,注意這里是 sh命令 docker exec -it redis-1 /bin/sh
# 創建集群
redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379 -- cluster-replicas 1
# 連接集群 redis-cli -c
# 查看集群資訊 cluster info
# 查看節點 cluster nodes
# set a b
# 停止到存值的容器
# 然后再次get a,發現依舊可以獲取值 # 查看節點,發現高可用完全沒問題

文章參考

[1]Docker官網.https://www.docker.com/[EB/OL].
[2]菜鳥Docker.https://www.runoob.com/docker/docker-tutorial.html[EB/OL].
[3]遇見狂神說.Docker最新超詳細版教程通俗易懂[EB/OL].2020-05-16/至今.

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/323292.html

標籤:其他

上一篇:用Rust語言開發Linux內核,得先過記憶體模型這關

下一篇:有了 HTTP 協議,為什么還需要 Websocket?

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more