centos安装Docker与使用构建业务镜像挂载卷harbor仓库的高可用及网络模式和资源限制介绍...
Docker版本選擇:
? ? Docker之前沒有區分版本,但是2017年推出(將docker更名為)新的項目Moby,github地址:https://github.com/moby/moby,Moby項目屬于Docker項目的全新上游,Docker將是一個隸屬于的Moby的子產品,而且之后的版本之后開始區別為CE版本(社區版本)和EE(企業收費版),CE社區版本和EE企業版本都是每個季度發布一個新版本,但是EE版本提供后期安全維護1年,而CE版本是4個月
Docker安裝
下載rpm包安裝:
官方rpm包下載地址: https : //download.docker.com/linux/centos/7/x86_64/stable/Packages/
阿里全世界下載地址: https ://mirrors.aliyun.com/docker-ce/linux/centos/7/x86_64/stable/Packages/
Centos yum源安裝:
Ubuntu安裝
版本:Ubuntu 18.04.3 參考:https ://yq.aliyun.com/articles/110806
- 阿里腳本安裝最新版
- 自定義版本下載
? ? ? ? 2. 安裝GPG證書
curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -? ? ? ? 3. 寫入軟件源信息
sudo add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"? ? ? ? 4. 更新
sudo apt-get -y update? ? ? ? 5. 發現Docker-CE的版本:
# apt-cache madison docker-ce docker-ce | 5:19.03.2~3-0~ubuntu-bionic | http://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages docker-ce | 5:19.03.1~3-0~ubuntu-bionic | http://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic/stable amd64 Packages? ? ? ? ?6. 安裝指定版本的Docker-CE:(VERSION例如上面的17.03.1?ce-0?ubuntu-xenial)
sudo apt install docker-ce-cli=5:18.09.9~3-0~ubuntu-bionic sudo apt install docker-ce=5:18.09.9~3-0~ubuntu-bionic? ? ? ? ?7. 驗證版本
解決方法:
sudo vim /etc/default/grub 在GRUB_CMDLINE_LINUX=""這行加上GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount=1"?更新下grub,然后重啟
sudo update-grub rebootDocker命令
? ? ? ? 4. 搜索nginx的鏡像(第一個是默認的,也是下載最多的)
docker search nginx?
? ? ? 5.? 下載nginx的鏡像
docker pull nginx?
? ? ? ? 6. 查看已經下載的鏡像列表,TAG版本號默認都是latest
docker images?
? ? ?7、進入容器后,安裝基礎命令:
apt update aptinstall procps apt install iputils-ping apt install net-tools啟動容器
# 啟動一個在后臺運行的 docker 容器 docker run -it -d --name 'test-nginx' nginx# -p指定端口映射, -p 80:80# 指定 ip 地址和傳輸協議 udp 或者 tcp: -p 192.168.7.108:80:80/tcp# 也可以在創建時手動指定容器的 dns --dns 223.6.6.6 # 指定名稱 --name "centos3"?
vi docker-enter.sh chmod +x docker-enter.sh?進入容器
?
?
? ? ? ? 3. 腳本方式進入容器
#!/bin/bash docker_in(){NAME_ID=$1PID=$(docker inspect -f "{{.State.Pid}}" ${NAME_ID})nsenter -t ${PID} -m -u -i -n -p }docker_in $1?啟動
./docker-enter.sh centos-test更多命令
以名義名:nginx為例子
?
? ? ? ? 2. 手動導出docker鏡像
docker save nginx -o /root/nginx.tar.gz docker save nginx > /root/nginx.tar.gzdocker加快加速配置:
? ? 國內下載國外的某些有時候會很慢,因此可以更改docker配置文件添加一個加速器,可以通過加速器達到加速下載替代的目的。
獲取加速地址:
瀏覽器打開http://cr.console.aliyun.com,編碼或登錄阿里云賬號,單擊垂直的嵌套加速器,將會得到一個專屬的加速地址,而且下面有使用配置說明:
?
? ? ? 1.?可以通過修改daemon配置文件/etc/docker/daemon.json來使用加速器
sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-'EOF' {"registry-mirrors": ["你的加速地址"] } EOF? ? ? 2. 重啟服務
sudo systemctl daemon-reload sudo systemctl restart docker使用docker?info?查看
Docker命令與鏡像管理:
Docker 鏡像含有啟動容器所需要的文件系統及所需要的內容, 因此鏡像主要用于創建并啟動 docker 容器。
Docker 鏡像含里面是一層層文件系統,叫做 Union FS(聯合文件系統) ,聯合文件系統,可以將幾層目錄掛載到一起,形成一個虛擬文件系統,虛擬文件系統的目錄結構就像普通 linux 的目錄結構一樣, docker 通過這些文件再加上宿主機的內核提供了一個 linux 的虛擬環境,每一層文件系統我們叫做一層 layer,聯合文件系統可以對每一層文件系統設置三種權限,只讀( readonly)、讀寫( readwrite)和寫出( whiteout-able),但是 docker 鏡像中每一層文件系統都是只讀的,構建鏡像的時候,從一個最基本的操作系統開始,每個構建的操作都相當于做一層的修改,增加了一層文件系統,一層層往上疊加,上層的修改會覆蓋底層該位置的可見性,這也很容易理解,就像上層把底層遮住了一樣,當使用鏡像的時候,我們只會看到一個完全的整體,不知道里面有幾層也不需要知道里面有幾層,結構如下:
一個典型的 Linux 文件系統由 bootfs 和 rootfs 兩部分組成, bootfs(boot filesystem) 主要包含 bootloader 和 kernel, bootloader 主要用于引導加載 kernel,
當 kernel 被加載到內存中后 bootfs 會被 umount 掉, rootfs (root file system) 包含的就是典型 Linux 系統中的/dev, /proc, /bin, /etc 等標準目錄和文件, 下圖就是 docker image 中最基礎的兩層結構,不同的 linux 發行版(如 ubuntu和 CentOS ) 在 rootfs 這一層會有所區別。但是對于 docker 鏡像通常都比較小, 官方提供的 centos 基礎鏡像在 200MB 左右,一些其他版本的鏡像甚至只有幾 MB, docker 鏡像直接調用宿主機的內核,鏡像中只提供 rootfs,也就是只需要包括最基本的命令、工具和程序庫就可以了, 比如 alpine 鏡像,在 5M 左右。
下圖就是有兩個不同的鏡像在一個宿主機內核上實現不同的 rootfs。
容器、 鏡像父鏡像:
docker常用命令示例
REPOSITORY #鏡像所屬的倉庫名稱
TAG #鏡像版本號(標識符), 默認為 latest
IMAGE ID #鏡像唯一 ID 標示
CREATED #鏡像創建時間
VIRTUAL SIZE #鏡像的大小
? ? ? ? ?刪除鏡像
docker rmi centosdocker命令:
子命令幫助
docker COMMAND --help 退出容器不注銷:Ctrl + P + Qrun
在新容器中運行命令
- 命令格式
- 常用選項
?例如:
前臺啟動并隨機映射本地端口到容器的 80
前臺啟動的會話窗口無法進行其他操作,除非退出, 但是退出后容器也會退出隨機端口映射, 其實是默認從 32768 開始
方式 1:本地端口 81 映射到容器 80 端口:
docker run -p 81:80 --name "nginx-test" nginx方式 2:本地 IP:本地端口:容器端口
docker run -p 192.168.10.205:82:80 --name "nginx-test" docker.io/nginx?方式 3:本地 IP:本地隨機端口:容器端口
docker run -p 192.168.10.205::80 --name "nginx-test" docker.io/nginx方式 4:本機 ip:本地端口:容器端口/協議,默認為 tcp 協議
docker run -p 192.168.10.205:83:80/udp --name "nginx-test" docker.io/nginx?方式 5:一次性映射多個端口+協議:
docker run -p 86:80/tcp -p 443:443/tcp -p 53:53/udp --name "nginx-test" docker.io/nginx? ? ? ? ?5. 后臺啟動容器
docker run -d -P --name "nginx-test" docker.io/nginxDns 服務,默認采用宿主機的 dns 地址
一是將 dns 地址配置在宿主機
二是將參數配置在 docker 啟動腳本里面 –dns=1.1.1.1
--rm 容器退出后會刪除容器
ps
列出正在運行的容器
- 命令格式
- 常用選項
?例:
rm
移除一個或多個容器
- 命令格式
- 常用選項
?例:
logs
獲取容器的日志
- 命令格式
- 常用選項
?例:
load
從tar存檔或STDIN加載鏡像
- 命令格式
- 常用選項
?例:
port
列出容器的端口映射或特定映射
- 命令格式
- 例:
stop
停止一個或多個正在運行的容器
- 命令格式
- 常用選項
?例:
kill
殺死一個或多個正在運行的容器
- 命令格式
- 常用選項
?例:
start
啟動一個或多個停止的容器
- 命令格式
- 常用選項
?例:
attach
此方式進入容器的操作都是同步顯示的且 exit 后容器將被關閉
- 命令格式
- 常用選項
?例:
docker attach 63fbc2d5a3ecexec
執行單次命令與進入容器,不是很推薦此方式, 雖然 exit 退出容器還在運行
- 命令格式
- 常用選項
例:
inspect
返回Docker對象的底層信息
- 命令格式
- 常用選項
例:
commit
從容器的更改中創建一個新鏡像
- 命令格式
- 常用選項
?例:
> 標記 tag 號,生產當中比較常用,后期可以根據 tag 標記創建不同版本的鏡像以及創建不同版本的容器。
Docker 鏡像與制作
Docker 鏡像有沒有內核?
從鏡像大小上面來說,一個比較小的鏡像只有十幾 MB,而內核文件需要一百多兆, 因此鏡像里面是沒有內核的, 鏡像在被啟動為容器后將直接使用宿主機的內核, 而鏡像本身則只提供相應的 rootfs, 即系統正常運行所必須的用戶空間的文件系統,比如/dev/, /proc, /bin, /etc 等目錄, 所以容器當中基本是沒有/boot目錄的,而/boot 當中保存的就是與內核相關的文件和目錄。
為什么沒有內核?
由于容器啟動和運行過程中是直接使用了宿主機的內核,所以沒有直接調用過物理硬件, 所以也不會涉及到硬件驅動, 因此也用不上內核和驅動,另外有內核的那是虛擬機。
手動制作nginx鏡像
Docker 制作類似于虛擬機的鏡像制作,即按照公司的實際業務務求將需要安裝的軟件、相關配置等基礎環境配置完成,然后將其做成鏡像,最后再批量從鏡像批量生產實例,這樣可以極大的簡化相同環境的部署工作, Docker 的鏡像制作分為手動制作和自動制作(基于 DockerFile), 企業通常都是基于 Dockerfile 制作精細, 其中手動制作鏡像步驟具體如下:
下載鏡像并初始化系統:
基于某個基礎鏡像之上重新制作, 因此需要先有一個基礎鏡像,本次使用官方提供的 centos 鏡像為基礎:
? ? 1. docker下載centos鏡像,并運行進入
- 進入容器
? ? ? ? ?4. 自定義 web 頁面
echo "Docker Yum Nginx" > /usr/share/nginx/html/index.html- 退出容器
? ? ? ? ? 5. 提交為鏡像:在宿主機基于容器 ID 提交為鏡像
docker commit -a "xu" -m "nginx_yum_v1" --change="EXPOSE 80 4433" 75f52cfb13d2 centos-nginx:v1?
帶 tag 的鏡像提交:
提交的時候標記 tag 號:
標記 tag 號,生產當中比較常用,后期可以根據 tag 標記創建不同版本的鏡像以及創建不同版本的容器。
? ? ? ? ?6. 查看創建的鏡像
docker image ls? ? ? ? 7. 從自己鏡像啟動容器,因為本機用的是云主機,沒有備案和域名,所以使用4433端口映射
docker run -d -p 4433:80 --name my-centos-nginx 87e99ab0c9ab? /usr/sbin/nginx # 87e99ab0c9ab 是IMAGE ID8. 訪問測試
?
?容器端口映射成功
Dockerfile介紹
? ?DockerFile 可以說是一種可以被 Docker 程序解釋的腳本, DockerFile 是由一條條的命令組成的,每條命令對應 linux 下面的一條命令, Docker 程序將這些DockerFile 指令再翻譯成真正的 linux 命令,其有自己的書寫方式和支持的命令, Docker 程序讀取 DockerFile 并根據指令生成 Docker 鏡像,相比手動制作鏡像的方式, DockerFile 更能直觀的展示鏡像是怎么產生的,有了 DockerFile,當后期有額外的需求時,只要在之前的 DockerFile 添加或者修改響應的命令即可重新生成新的 Docke 鏡像,避免了重復手動制作鏡像的麻煩。
FROM 指定基礎鏡像
定制鏡像,需要先有一個基礎鏡像,在這個基礎鏡像上進行定制。FROM 就是指定基礎鏡像,必需放在有效指令的第一行
怎么選擇合適的鏡像呢?官方有nginx、redis、mysql、httpd、tomcat等服務類的鏡像,也有操作系統類,如:centos、ubuntu、debian等。
例:
FROM centos:latestMAINTAINER 指定維護者信息
格式
MAINTAINER <name>RUN 執行命令
RUN 指令是用來執行命令的。shell命令功能豐富,所以RUN 指令經常用來調用shell指令。
格式
RUN <command> # 或 RUN ["executable", "param1", "param2"] 第一種不用多說,第二種方式:RUN ["/bin/bash", "-c", "echo hello world"]
Dockerfile中,每一個指令都會創建一層鏡像,RUN寫多了,創建的鏡像層數就會增多,所以一般RUN 指令的寫法為
CMD 啟動容器時執行的命令
指定啟動容器時執行的命令,每個 Dockerfile 只能有一條 CMD 命令。如果指定了多條命令,只有最后一條會被執行。
支持三種格式
# 使用 exec 執行,推薦方式; CMD ["executable","param1","param2"] # 在 /bin/sh 中執行,提供給需要交互的應用; CMD command param1 param2 # 提供給 ENTRYPOINT 的默認參數; CMD ["param1","param2"]如果用戶啟動容器時候指定了運行的命令,則會覆蓋掉 CMD 指定的命令。
EXPOSE 分配端口號
告訴 Docker 服務端容器暴露的端口號,供互聯系統使用。在啟動容器時需要通過 -P,Docker 主機會自動分配一個端口轉發到指定的端口
格式
EXPOSE <port> [<port>...]ENV 環境變量
指定一個環境變量,會被后續 RUN 指令使用,并在容器運行時保持。
格式
ENV <key> <value>例如
ENV PG_MAJOR 9.3 ENV PG_VERSION 9.3.4 RUN curl -SL http://example.com/postgres-$PG_VERSION.tar.xz | tar -xJC /usr/src/postgress && … ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATHADD 復制/解壓
該命令將復制指定的 <src> 到容器中的 <dest>。 其中<src> 可以是Dockerfile所在目錄的一個相對路徑;也可以是一個 URL;還可以是一個 tar 文件(自動解壓為目錄)
格式
ADD <src> <dest>COPY 復制
復制本地主機的 <src>(為 Dockerfile 所在目錄的相對路徑)到容器中的 <dest>
格式
COPY <src> <dest>當使用本地目錄為源目錄時,推薦使用 COPY
ENTRYPOINT 容器啟動后執行的命令
配置容器啟動后執行的命令,并且不可被 docker run 提供的參數覆蓋。
兩種格式:
ENTRYPOINT ["executable", "param1", "param2"]# shell中執行 ENTRYPOINT command param1 param2每個 Dockerfile 中只能有一個 ENTRYPOINT,當指定多個時,只有最后一個起效
VOLUME 掛載點
創建一個可以從本地主機或其他容器掛載的掛載點,一般用來存放數據庫和需要保持的數據等
格式
VOLUME ["/data"]。USER 指定用戶名
指定運行容器時的用戶名或 UID,后續的 RUN 也會使用指定用戶
格式
USER daemon當服務不需要管理員權限時,可以通過該命令指定運行用戶。并且可以在之前創建所需要的用戶,
例如:
RUN groupadd -r postgres && useradd -r -g postgres postgres要臨時獲取管理員權限可以使用 gosu,而不推薦 sudo。
WORKDIR 工作目錄
為后續的 RUN、CMD、ENTRYPOINT 指令配置工作目錄
格式
WORKDIR /path/to/workdir。可以使用多個 WORKDIR 指令,后續命令如果參數是相對路徑,則會基于之前命令指定的路徑。例如
WORKDIR /a WORKDIR b WORKDIR c RUN pwd?則最終路徑為 /a/b/c。
ONBUILD
配置當所創建的鏡像作為其它新創建鏡像的基礎鏡像時,所執行的操作指令。
格式
ONBUILD [INSTRUCTION]?例如,Dockerfile 使用如下的內容創建了鏡像 image-A。
... ONBUILD ADD . /app/src ONBUILD RUN /usr/local/bin/python-build --dir /app/src ...如果基于 image-A 創建新的鏡像時,新的Dockerfile中使用 FROM image-A指定基礎鏡像時,會自動執行ONBUILD 指令內容,等價于在后面添加了兩條指令。
FROM image-A#Automatically run the following ADD . /app/src RUN /usr/local/bin/python-build --dir /app/src使用 ONBUILD 指令的鏡像,推薦在標簽中注明,例如 ruby:1.9-onbuild
構建鏡像
格式
docker build [選項] 路徑? ?-t選項,指定鏡像的標簽信息
docker build -t nginx:v1 /usr/local/src/構建時,目錄內除了構建所需要的文件,不要有其它文件
DockerFile 制作yum版 nginx 鏡像:
RUN就是運行shell命令
ADD
構建?
?? ? ? ? 6. 查看鏡像
docker images# curl 127.0.0.1:8355
<h1> docker nginx test, nginx container by dockerfile</h1>
DockerFile 制作編譯版 nginx 鏡像:
下載鏡像并初始化系統:
docker pull centos mkdir -pv /opt/dockerfile/web/nginx目錄結構按照業務類型或系統類型等方式劃分,方便后期鏡像比較多的時候進行分類
編寫 Dockerfile:
vim /opt/dockerfile/web/nginx/Dockerfile 生成的鏡像的時候會在執行命令的當前目錄查找 Dockerfile 文件, 所以名稱不可寫錯, 而且 D 必須大寫
My Dockerfile
"#"為注釋,等于 shell 腳本的中#
除了注釋行之外的第一行,必須是 From xxx (xxx 是基礎鏡像)
準備源碼包與配置文件:
? ? ? ? ?4.?開始構建:可以清晰看到各個步驟執行的具體操作
構建成功了
?
? ? ? ? ?5. 查看是否生成本地鏡像,如果構建時出錯可能會導致生成名字為none的鏡像,使用命令刪除即可
docker images? docker rmi -f $(docker images | grep "none" | awk '{print $3}')? #過濾出倉庫名和tag名為none的鏡像ID并強制刪除
? ? ? ? ?6. 從鏡像啟動容器
docker run -d -p 80:80 --name mak1e-nginx peterhx/nginx-make-1.16.1:v1 /usr/sbin/nginx制作 tomcat 鏡像:
基于官方提供的 centos 7.6. 基礎鏡像構建 JDK 和 tomcat 鏡像,先構建 JDK 鏡像,然后再基于 JDK 鏡像構建 tomcat 鏡像。
1、先構建 JDK 鏡像
cd /opt/dockerfile/web/jdk/
將 JDK 壓縮包上傳到 Dockerfile 當前目錄,然后執行構建:
profile文件內容,(最下邊聲明的環境變量,其他的一樣)
# cat profile########################### # System wide environment and startup programs, for login setup # Functions and aliases go in /etc/bashrc# It's NOT a good idea to change this file unless you know what you # are doing. It's much better to create a custom.sh shell script in # /etc/profile.d/ to make custom changes to your environment, as this # will prevent the need for merging in future updates.pathmunge () {case ":${PATH}:" in*:"$1":*);;*)if [ "$2" = "after" ] ; thenPATH=$PATH:$1elsePATH=$1:$PATHfiesac }if [ -x /usr/bin/id ]; thenif [ -z "$EUID" ]; then# ksh workaroundEUID=`/usr/bin/id -u`UID=`/usr/bin/id -ru`fiUSER="`/usr/bin/id -un`"LOGNAME=$USERMAIL="/var/spool/mail/$USER" fi# Path manipulation if [ "$EUID" = "0" ]; thenpathmunge /usr/sbinpathmunge /usr/local/sbin elsepathmunge /usr/local/sbin afterpathmunge /usr/sbin after fiHOSTNAME=`/usr/bin/hostname 2>/dev/null` HISTSIZE=1000 if [ "$HISTCONTROL" = "ignorespace" ] ; thenexport HISTCONTROL=ignoreboth elseexport HISTCONTROL=ignoredups fiexport PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL# By default, we want umask to get set. This sets it for login shell # Current threshold for system reserved uid/gids is 200 # You could check uidgid reservation validity in # /usr/share/doc/setup-*/uidgid file if [ $UID -gt 199 ] && [ "`/usr/bin/id -gn`" = "`/usr/bin/id -un`" ]; thenumask 002 elseumask 022 fifor i in /etc/profile.d/*.sh /etc/profile.d/sh.local ; doif [ -r "$i" ]; thenif [ "${-#*i}" != "$-" ]; then . "$i"else. "$i" >/dev/nullfifi doneunset i unset -f pathmungeexport JAVA_HOME=/usr/local/jdk export TOMCAT_HOME=/apps/tomcat export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$TOMCAT_HOME/bin:$PATH export CLASSPATH=.$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib:$JAVA_HOME/lib/tools.jar
執行構建
cat build-command.sh #!/bin/bash docker build -t centos-jdk1.8:v1 .?
? ? ? ? 5. 啟動容器
docker run -it centos-jdk1.8:v1 bash?進入容器后,要能查看到Java的環境(如果查不出來等于白做,檢查是哪個環節出錯)
?
2、從 JDK 鏡像構建 tomcat-8 鏡像
上傳 tomcat 壓縮包:apache-tomcat-8.5.42.tar.gz
通過腳本構建 tomcat 基礎鏡像
?
?訪問測試
制作 haproxy 鏡像:
準備 haproxy 源碼文件:haproxy-2.0.5.tar.gz
準備run_haproxy.sh腳本
? ? ? ? 6. 準備構建腳本:
docker build -t haproxy:v1 .? ? ? ? ?7. 從鏡像啟動容器:
docker run -it -d -p 80:80 -p 9999:9999 haproxy:v1? ? ? ? ?8. web 訪問驗證
9. 訪問tomcat業務app1
本地鏡像上傳至官方 docker 倉庫:
將自制的鏡像上傳至 docker 倉庫; https://hub.docker.com/
登錄到 docker hub 創建官網創建賬戶, 登錄后點擊 settings 完善賬戶信息,填寫賬戶基本信息
在虛擬機使用自己的賬號登錄
#登錄成功之后會在當前目錄生成一個隱藏文件用于保存登錄認證信息
上傳完成
7. 到 docker 官網驗證
8. 更換到其他 docker 服務器下載鏡像
# 登錄 docker login docker.io # 下載 docker pull peterhx/alpine-test:alpine123 # 查看 docker imagesdocker 倉庫之分布式 Harbor
Harbor 是一個用于存儲和分發 Docker 鏡像的企業級 Registry 服務器,由vmware 開源,其通過添加一些企業必需的功能特性,例如安全、標識和管理等,擴展了開源 Docker Distribution。作為一個企業級私有 Registry 服務器,Harbor 提供了更好的性能和安全。提升用戶使用 Registry 構建和運行環境傳輸鏡像的效率。 Harbor 支持安裝在多個 Registry 節點的鏡像資源復制,鏡像全部保存在私有 Registry 中, 確保數據和知識產權在公司內部網絡中管控, 另外,Harbor 也提供了高級的安全特性,諸如用戶管理,訪問控制和活動審計等。
官網地址: https://vmware.github.io/harbor/cn/, 官方 github 地址:https://github.com/vmware/harbor
Harbor 功能官方介紹:
基于角色的訪問控制:用戶與 Docker 鏡像倉庫通過“項目”進行組織管理,一個用戶可以對多個鏡像倉庫在同一命名空間(project)里有不同的權限。鏡像復制:鏡像可以在多個 Registry 實例中復制(同步)。尤其適合于負載均衡,高可用,混合云和多云的場景。圖形化用戶界面:用戶可以通過瀏覽器來瀏覽,檢索當前 Docker 鏡像倉庫,管理項目和命名空間。
AD/LDAP: Harbor 可以集成企業內部已有的 AD/LDAP,用于鑒權認證管理。
審計管理:所有針對鏡像倉庫的操作都可以被記錄追溯,用于審計管理。國際化:已擁有英文、中文、德文、日文和俄文的本地化版本。更多的語言將會添加進來。RESTful API - RESTful API :提供給管理員對于 Harbor 更多的操控, 使得與其它管理軟件集成變得更容易。
部署簡單:提供在線和離線兩種安裝工具, 也可以安裝到 vSphere 平臺(OVA 方式)虛擬設備。
安裝 Harbor:
下載地址: https://github.com/goharbor/harbor/releases
安裝文檔: https://github.com/vmware/harbor/blob/master/docs/installation_guide.md
本次使用 harbor 版本 1.2.2 離線安裝包,具體名稱為 harbor-offline-installer-v1.7.5.tgz
下載 Harbor 安裝包:
方式1:下載離線安裝包:https://github.com/goharbor/harbor/releases
cd /usr/local/src/ wget https://storage.googleapis.com/harbor-releases/release-1.7.0/harbor-offline-installer-v1.7.5.tgz方式2:下載在線安裝包
cd /usr/local/src/ wget https://storage.googleapis.com/harbor-releases/release-1.7.0/harbor-online-installer-v1.7.5.tgz配置安裝 Harbor:?
在另一臺云主機的機器(內網IP為:192.168.0.59)上安裝harbor倉庫
?安裝docker-compose時報錯,缺少依賴及python的開發環境,yum install -y gcc python-devel?即可
st或127.0.0.1 hostname = 192.168.0.59# 訪問UI和令牌/通知服務的協議 ui_url_protocol = http# harbor DB的根用戶的密碼 db_password = root123# 最大進程數 max_job_workers = 3# 確定是否為注冊表的令牌生成證書 customize_crt = on# 證書路徑 ssl_cert = /data/cert/server.crt ssl_cert_key = /data/cert/server.key# 密鑰存儲的路徑 secretkey_path = /data# Admiral的url,注釋此屬性,或在Harbor獨立時將其值設置為NA admiral_url = NA# Clair的postgres數據庫的密碼 clair_db_password = root123# 電子郵件服務器 email_identity = harbor email_server = smtp.qq.com email_server_port = 25 email_username = hanxu@foxmail.com email_password = 123 email_from = admin <hanxu@foxmail.com> email_ssl = false email_insecure = false# 啟動后從UI更改管理密碼。 harbor_admin_password = root123# 如果希望根據LDAP服務器驗證用戶的憑證,請將其設置為ldap_auth。 auth_mode = db_auth ldap_url = ldaps://ldap.mydomain.com ldap_basedn = ou=people,dc=mydomain,dc=com ldap_uid = uid ldap_scope = 3 ldap_timeout = 5 # 打開或關閉自注冊功能 self_registration = on# 令牌服務創建的令牌的過期時間 token_expiration = 30# 設置為“adminonly”,以便只有管理員用戶才能創建項目 # 默認值“everyone”允許每個人創建一個項目 project_creation_restriction = everyone# verify_remote_cert = on
? ? ?4.?準備
./prepare?docker-compose.yml 文件,用于配置數據目錄等配置信息? ??
?
? ? ? ?5.?運行當前目錄下的腳本開始安裝
./install.sh?
安裝完成,可以通過設定的連接通過瀏覽器進行訪問(默認使用的是80,加密端口是443,此主機沒有備案所以下面還需要修改一下端口)
后期修改配置:
如果 harbor 運行一段時間之后需要更改配置,則步驟如下:這里順便修改一下harbor倉庫的訪問的默認端口
1.?先停止 harbor:
2. 編輯 harbor.cfg 進行相關配置:(修改之前一定要記得先copy一份)
vim harbor.cfg # 主配置文件不需要修改# 修改docker-compose.yml文件,默認訪問的端口映射為888端口① 這里修改了兩個端口 80改為888,443改為了4433
② 修改完之后還要修改一個文件
# pwd /usr/local/harbor/common/templates/registry [root@Server2 registry]# ls config.yml config.yml.bak root.crt [root@Server2 registry]# vim config.ymlurl后加上修改后的默認端口,保存退出
?
?③?修改docker的啟動文件
#vim /usr/lib/systemd/system/docker.service 修改如下一行 ExecStart=/usr/bin/dockerd --insecure-registry=x.x.x.x:888修改后重新加載并重啟服務
systemctl daemon-reload && systemctl restart docker.service3. prepare
./prepare4. 啟動 harbor 服務:
docker-compose start?登錄測試一下,登錄成功
?
常見的2個報錯信息解答:
(1)Error response from daemon: Get https://192.168.0.59/v1/users/: dial tcp 192.168.0.59:443: getsockopt: connection refused
(2)Error response from daemon: Get https://192.168.0.59:888/v1/users/: http: server gave HTTP response to HTTPS client
報這2個錯誤的都是如下2個原因:
1、是端口錯了!
2、未在docker啟動文件中添加--insecure-registry信任關系!
大多數這個錯誤是第2個原因,因為你沒有添加信任關系的話,docker默認使用的是https協議,所以端口不對(443),會報連接拒絕這個錯誤;
或者提示你 "服務器給HTTPS端的是HTTP響應" 這個錯誤,因為你沒添加端口信任,服務器認為這是默認的https訪問,返回的卻是http數據!
解決方法:
正確的添加信任關系包括端口號:
--insecure-registry=192.168.0.59:888
一定要把主機與端口同時添加進去!
繼續
?2.?查看本地端口
3. web?瀏覽器訪問 Harbor 管理界面
?如果可以正常登錄就說明之前的配置沒毛病,下面就可上傳鏡像了
配置 docker 使用 harbor 倉庫上傳下載鏡像:
注意:如果我們配置的是 https 的話,本地 docker 就不需要有任何操作就可以訪問 harbor 了,在第一臺主機的docker啟動文件中也添加上內網harbor倉庫的地址
在ExecStart追加
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --insecure-registry 192.168.0.59:888?
?如果這里突然遇到密碼錯誤(確認不是忘記了密碼),可以試試重啟docker-compose
docker-compose stop docker-compose start> 修改 images 的名稱,不修改成指定格式無法將鏡像上傳到 harbor 倉庫,格式為: HarborIP/項目名/image 名字:版本號:
首先要新建一個項目,進入項目里,右側推送鏡像,按照指定格式進行修改才能上傳到此項目中來
將鏡像 push 到 harbor:因為默認上傳時使用加密的傳輸方式也就是https,這里因為修改了端口所以有些區別
格式為: docker push 鏡像名:版本
harbor 界面驗證鏡像上傳成功
驗證鏡像信息
從 harbor 下載鏡像并啟動容器:
目前凡是需要從 harbor 鏡像服務器下載 image 的 docker 服務都要更改,不更改的話無法下載:
在ExecStart追加ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --insecure-registry 192.168.0.59:888
? ? ? ?3. 查看下載命令:
執行下載:
7. 成功啟動,并可以正常使用
實現 harbor 高可用:
Harbor 支持基于策略的 Docker 鏡像復制功能, 這類似于 MySQL 的主從同步, 其可以實現不同的數據中心、 不同的運行環境之間同步鏡像, 并提供友好的管理界面,大大簡化了實際運維中的鏡像管理工作,已經有用很多互聯網公司使用harbor 搭建內網 docker 倉庫的案例,并且還有實現了雙向復制的案列,本文將實現單向復制的部署:
1. 新部署一臺 harbor2 服務器192.168.0.36
過程見前一節
- 主 harbor :192.168.0.59
復制的原理是從源harbor上推到目標harbor,所以下面的配置是要在之前創建的harbor上配置。
主harbor:192.168.0.59
從harbor:192.168.0.36
主 harbor:測試連接成功后,確定
從 harbor2:創建一個 alpine 項目:
與主 harbor1 項目名稱保持一致:
主 harbor:配置復制
主 harbor:點擊復制,新建規則:
主 harbor:編輯同步策略
主 harbor:查看鏡像同步狀態
從 harbor:查看鏡像是否同步成功
測試從 harbor 鏡像下載和容器啟動:
在ExecStart追加
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --insecure-registry 192.168.0.36:888 --insecure-registry 192.168.0.59:888其中 192.168.0.36/59 是我們部署 Harbor 的地址,即 hostname 配置項值。配置完后需要重啟 docker 服務。
docker 客戶端下載鏡像
? ? ? ? ?5. 下載完后查看鏡像
至此,高可用模式的 harbor 倉庫部署完畢
Docker 數據管理
如果運行中的容器修如果生成了新的數據或者修改了現有的一個已經存在的文件內容,那么新產生的數據將會被復制到讀寫層進行持久化保存,這個讀寫層也就是容器的工作目錄,此即“寫時復制(COW) copy on write”機制
數據類型:
Docker 的鏡像是分層設計的,底層是只讀的,通過鏡像啟動的容器添加了一層可讀寫的文件系統,用戶寫入的數據都保存在這一層當中,如果要將寫入的數據永久生效,需要將其提交為一個鏡像然后通過這個鏡像在啟動實例,然后就會給這個啟動的實例添加一層可讀寫的文件系統,目前 Docker 的數據類型分為兩種, 一是數據卷, 二是數據容器,數據卷類似于掛載的一塊磁盤,數據容器是將數據保存在一個容器上
LowerDir: image 鏡像層(鏡像本身,只讀) UpperDir:容器的上層(讀寫) MergedDir:容器的文件系統,使用 Union FS(聯合文件系統)將 lowerdir 和 WorkDir:容器在 宿主機的工作目錄
什么是數據卷(data volume):
數據卷實際上就是宿主機上的目錄或者是文件,可以被直接 mount 到容器當中使用。
實際生成環境中,需要針對不同類型的服務、 不同類型的數據存儲要求做相應的規劃, 最終保證服務的可擴展性、 穩定性以及數據的安全性。
如下圖:
左側是無狀態的 http 請求服務, 右側為有狀態。
下層為不需要存儲的服務,上層為需要存儲的部分服務
創建 APP 目錄并生成 web 頁面:
此 app 以數據卷的方式,提供給容器使用, 比如容器可以直接宿主機本地的 web_app,而需要將代碼提前添加到容器中,此方式適用于小型 web 站點。
mkdir /data/testapp –p echo "testapp page" > /data/testapp/index.html在宿主機或容器修改數據
啟動容器并驗證數據:
啟動兩個容器, web1 容器和 web2 容器, 分別測試能否在容器內訪問到宿主機的添加的數據。
注意使用 -v 參數, 將宿主機目錄映射到容器內部, web2 的 ro 標示在容器內對該目錄只讀,默認是可讀寫的:
2、web 界面訪問(這里使用命令行測試)
3、刪除容器
? ? 刪除容器的時候指定參數-v, 可以刪除/var/lib/docker/containers/的容器數據目錄,但是不會刪除數據卷的內容
docker rm -fv d044730c0f4f數據卷的特點及使用:
1、數據卷是宿主機的目錄或者文件,并且可以在多個容器之間共同使用。 2、 在宿主機對數據卷更改數據后會在所有容器里面會立即更新。 3、數據卷的數據可以持久保存,即使刪除使用使用該容器卷的容器也不影響。 4、 在容器里面的寫入數據不會影響到鏡像本身。
文件掛載: 文件掛載用于很少更改文件內容的場景, 比如 nginx 的配置文件、 tomcat 的配置文件等
數據卷使用場景:
1、 日志輸出
2、 靜態 web 頁面
3、 應用配置文件
4、 多容器間目錄或文件共享
如何一次掛載多個目錄
? ? ? ? ? 3. 驗證 web 訪問
數據卷容器:
? ? ? ?數據卷容器功能是可以讓數據在多個 docker 容器之間共享,即可以讓 B 容器訪問 A 容器的內容,而容器 C 也可以訪問 A 容器的內容,\
即先要創建一個后臺運行的容器作為 Server,用于卷提供, 這個卷可以為其他容器提供數據存儲服務,其他使用此卷的容器作為 client 端:
啟動一個卷容器 Server:
先啟動一個容器, 并掛載宿主機的數據目錄:
將宿主機的 catalina.sh 啟動腳本和 chen 的 web 頁面,分別掛載到卷容器 server端,然后通過 server 端共享給 client 端使用。
三個容器訪問到的數據是一樣的
進入其它一個容器,修改網站的默認測試頁面
5. 驗證宿主機數據
# cat /data/nginx/index.html 3333停止了卷服務的容器,還可以從這個卷服務容器啟動新的容器
[root@Server1 ~]# docker run -d --name web7 -p 87:80 --volumes-from volume-server nginx
docker: Error response from daemon: No such container: volume-server.
# 這里就不行了,報錯
重新創建容器卷 Server
docker run -d --name volume-server \-v /data/app/nginx.conf:/etc/nginx/nginx.conf:ro \-v /data/nginx:/usr/share/nginx/html \nginx創建出 volume server 之后, 就可以創建基于 volume server 的新容器。
docker run -d --name web8 -p 88:80 \--volumes-from volume-server nginx? ?在當前環境下, 即使把提供卷的容器 Server 刪除, 已經運行的容器 Client 依然可以使用掛載的卷, 因為容器是通過掛載訪問數據的, 但是無法創建新的卷容器客戶端, 但是再把卷容器 Server 創建后即可正常創建卷容器 Client,
此方式可以用于線上共享數據目錄等環境, 因為即使數據卷容器被刪除了,其他已經運行的容器依然可以掛載使用
? ?數據卷容器可以作為共享的方式為其他容器提供文件共享,類似于 NFS 共享,可以在生產中啟動一個實例掛載本地的目錄,然后其他的容器分別掛載此容器的目錄,即可保證各容器之間的數據一致性。
十五:
主要介紹docker網絡相關知識,docker服務安裝完成之后,至少在每個主機機會生成一個名稱為docker0的網卡 其IP地址都是172.17.0.1/16,并且會生成某種不同類型的網絡,如下圖:
docker結合負載實現網站高可用:
整體規劃圖: 下圖為一個小型的網絡架構圖,其中nginx使用docker運行
| 服務器1 | centos 7.6 | 192.168.99.101 |
| 服務器2 | centos 7.6 | 192.168.99.102 |
| 碼頭工人1 | Ubuntu的04.04 | 192.168.99.22 |
| 碼頭工人2 | Ubuntu的04.04 | 192.168.99.23 |
1.安裝并配置keepalived
啟動
systemctl restart keepalived systemctl enable keepalived配置
vim /etc/keepalived/keepalived.conf ! Configuration File for keepalivedglobal_defs {notification_email {root@localhost}notification_email_from root@localhostsmtp_server localhostsmtp_connect_timeout 30router_id LVS_DEVEL2vrrp_skip_check_adv_addr #vrrp_strictvrrp_iptablesvrrp_garp_interval 0vrrp_gna_interval 0 } vrrp_instance MAKE_VIP_INT {state BACKUPinterface eth0virtual_router_id 1priority 50authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {192.168.99.10 dev eth0 label eth0:1} }啟動
systemctl restart keepalived systemctl enable keepalived2.安裝并配置haproxy
3. docker服務器啟動nginx容器并驗證
驗證網絡訪問
驗證網絡訪問
Server1 haproxy狀態頁面:192.168.99.101:9999 / haproxy-status
Server2 haproxy狀態頁面:192.168.99.102:9999 / haproxy-status
容器之間的互聯
通過容器名稱互聯:
即在同一個主機上的容器之間可以通過自定義的容器名稱相互訪問,某個業務前端靜態頁面是使用nginx,動態頁面使用的是tomcat,由于容器在啟動的時候其內部IP地址是DHCP隨機分配的,所以如果通過內部訪問的話,自定義名稱是相對比較固定的,因此比較適用于此場景。
可能需要先安裝ping工具
apt-get update && apt install -y iputils-ping通過自定義容器別名互聯:
上一步驟中,自定義的容器名稱可能后期會發生變化,那么一旦名稱發生變化,程序之間也要隨之發生變化,此類程序通過容器名稱進行服務調用,但是容器名稱發生變化之后再使用之前的名稱肯定是無法成功調用,每次都進行更改的話又比較麻煩,因此可以使用自定義別名的方式解決,即容器名稱可以隨意更容易,只要不更改別名即可,具體如下:
命令格式:
docker網絡類型:
docker的網絡使用docker network ls命令看到有一種類型,下面將介紹每一種類型的具體工作方式:使用參數–net=網絡類型指定,而不指定替代就是bridge模式。查看當前docke的網卡信息:
docker network list網橋:可以,使用自定義IP 主機:不獲取IP直接使用物理機IP,并監聽物理機IP監聽端口 無:沒有網絡
(1)主機模式:使用參數–net = host指定。 啟動的容器如果指定了使用主機模式,那么新創建的容器不會創建自己的虛擬網卡,而是直接使用托管機的網卡和IP地址,因此在容器里面查看到的IP信息就是宿主機的信息,
訪問容器的時候直接使用主機機IP +容器端口即可,不過容器的其他資源他們必須文件系統,系統進程等還是和主機保持隔離。模式的網絡性能最高,但是各個容器之間的端口不能相同,適用于運行容器端口比較固定的業務。
? ? ? ? ? 2. 啟動一個新容器,并指定網絡模式為主機
docker run -d --name app1 --net=host nginx? ? ? ? ?3. 訪問主機機驗證因為是主機模式,所以直接訪問主機機的IP:192.168.0.36
訪問到的是nginx的默認首頁
主機模式不支持端口映射,當指定端口映射的時候會提示如下警告信息: 使用主機網絡模式時,將替換已指定的端口
docker run -d --name app2 -p 81:80 --net=host nginx(2)None模式:使用參數–net = none指定 在使用none模式后,Docker容器不會進行任何網絡配置,其沒有網卡,沒有IP也沒有路由,因此無法與外部通信,需要手動添加網卡配置IP等,所以極少使用
命令使用方式:
docker run -it -d --name net_none -p 80:80 --net=none nginx(3)容器模式:使用參數–net = container:name或ID
使用此模式創建的容器需要指定和一個已經存在的容器共享一個網絡,而不是和容納機共享網,新創建的容器不會創建自己的網卡也不會配置自己的IP,或者和一個已經存在的被指定的容器IP和端口范圍,
因此該容器的端口不能和被指定的端口沖突,除了網絡之外的文件系統,進展信息等仍保持相互隔離,兩個容器的進展可以通過lo網卡及容器IP進行通信。
(4)bridge模式: docker的交替模式即不指定任何模式就是bridge模式,也是使用比較多的模式,此模式創建的容器會為每一個容器分配自己的網絡IP等信息,且多個容器連接到一個虛擬網橋與外界通信
查看bridge模式的信息
docker network inspect bridge?
docker跨主機互聯之簡單實現:
? ? ?跨主機互聯是說A主機的容器可以訪問B主機上的容器,但是可以保證各主機之間的網絡是可以相互通信的,然后各容器才可以通過主機訪問到對方的容器,實現原理是在主機做一個網絡路由就可以實現A主機的容器訪問B主機的容器的目的,
復雜的網絡或者大型的網絡可以使用google開源的k8s進行互聯。
? 修改各主機機網段: Docker的替代網段是172.17.0.x / 24,而且每個主機機都是一樣的,因此路由選擇的路由就是各個主機的網絡不能一致,具體如下:
服務器A:192.168.0.36 服務器B:192.168.0.59
在ExecStart結尾追加--bip=10.10.0.1/24,ip是你想設置的網絡的網關ip
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --bip=10.10.0.1/24如果你的系統是Centos,需要打開ipforward
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf sysctl -p?
在ExecStart結尾追加--bip=10.20.0.1/24,注意不能跟服務器A一樣
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --bip=10.20.0.1/24?
容器間互相ping測試 互連兩臺服務器分別啟動兩個容器進行測試:10.10.0.0網段是服務器A內的容器,10.20.0.0網段是服務器B內的容器
?在另一臺容器里反ping試一下
如果可以ping通就表示沒有問題,兩個不同宿主機上的容器可以互相通信了
創建自定義網絡:
可以基于docker命令創建自定義網絡,自定義網絡可以自定義IP地域和網關等信息。
幫助
docker network create –help?
?
? docker run -it? centos-nginx:v1 bash
[root@ed06c2785c92 /]# ifconfig eth0 [root@ed06c2785c92 /]# ping www.baidu.com保存下iptbales
? ? ? ? ? ? ?#?vim iptables.sh
把DOCKER-ISOLATION-STAGE-2除了RETURN結尾的都注釋了
? ? ? ? ? 4.?驗證通信
先看一下其他網段的容器ip地址
?ping測試一下
?
經過以上的配置,目前就已經實現了不通網絡間的通信
十六、Docker資源限制
官網:https://docs.docker.com/config/containers/resource_constraints/
默認情況下, 容器沒有資源限制, 可以使用主機內核調度程序允許的盡可能多的給定資源, Docker 提供了控制容器可以限制容器使用多少內存或 CPU 的方法,設置 docker run 命令的運行時配置標志。
其中許多功能都要求宿主機的內核支持 Linux 功能, 要檢查支持, 可以使用docker info 命令,如果內核中禁用了某項功能, 可能會在輸出結尾處看到警告,
如下所示:
WARNING: No swap limit support對于 Linux 主機, 如果沒有足夠的內容來執行其他重要的系統任務, 將會拋出OOM (Out of Memory Exception,內存溢出、 內存泄漏、 內存異常), 隨后系統會開始殺死進程以釋放內存, 凡是運行在宿主機的進程都有可能被 kill, 包括 Dockerd和其它的應用程序, 如果重要的系統進程被 Kill,會導致和該進程相關的服務全部宕機。
產生 OOM 異常時, Dockerd 嘗試通過調整 Docker 守護程序上的 OOM 優先級來減輕這些風險,以便它比系統上的其他進程更不可能被殺死,但是容器的 OOM優先級未調整, 這使得單個容器被殺死的可能性比 Docker 守護程序或其他系統進程被殺死的可能性更大,不推薦通過在守護程序或容器上手動設置--oomscore-adj 為極端負數,或通過在容器上設置--oom-kill-disable 來繞過這些安全措施。
OOM 優先級機制:
linux 會為每個進程算一個分數,最終他會將分數最高的進程 kill。
/proc/PID/oom_score_adj :范圍為-1000 到 1000,值越高越容易被宿主機 kill掉,如果將該值設置為-1000,則進程永遠不會被宿主機 kernel kill。
/proc/PID/oom_adj :范圍為-17 到+15,取值越高越容易被干掉,如果是-17,則表示不能被 kill,該設置參數的存在是為了和舊版本的 Linux 內核兼容。
/proc/PID/oom_score :這個值是系統綜合進程的內存消耗量、 CPU 時間(utime + stime)、存活時間(uptime - start time)和 oom_adj 計算出的,消耗內存越多分越高,存活時間越長分越低。
容器的內存限制:
Docker 可以強制執行硬性內存限制,即只允許容器使用給定的內存大小。
Docker 也可以執行非硬性內存限制,即容器可以使用盡可能多的內存,除非內核檢測到主機上的內存不夠用了。
--oom-score-adj: 宿主機 kernel 對進程使用的內存進行評分, 評分最高的將被宿主機內核 kill 掉, 可以指定一個容器的評分制但是不推薦手動指定。
--oom-kill-disable: 對某個容器關閉 oom 機制。
內存限制參數:
-m, --memory:容器可以使用的最大內存量,如果設置此選項,則允許的最內存值為 4m (4 兆字節)。
--memory-swap: 容器可以使用的交換分區大小, 必須要在設置了物理內存限制的前提才能設置交換分區的限制
--memory-swappiness: 設置容器使用交換分區的傾向性,值越高表示越傾向于使用 swap 分區,范圍為 0-100, 0 為能不用就不用, 100 為能用就用。
--kernel-memory: 容器可以使用的最大內核內存量,最小為 4m,由于內核內存與用戶空間內存隔離,因此無法與用戶空間內存直接交換,因此內核內存不足的容器可能會阻塞宿主主機資源,這會對主機和其他容器或者其他服務進程產生影響,因此不要設置內核內存大小。
--memory-reservation:允許指定小于--memory 的軟限制,當 Docker 檢測到主機上的爭用或內存不足時會激活該限制,如果使用--memory-reservation,則必須將其設置為低于--memory 才能使其優先。 因為它是軟限制,所以不能保證容器不超過限制。
--oom-kill-disable 默認情況下,發生 OOM 時, kernel 會殺死容器內進程,但是可以使用--oom-kill-disable 參數,可以禁止 oom 發生在指定的容器上,即 僅在已設置-m選項的容器上禁用 OOM,如果-m 參數未配置,產生 OOM 時,主機為了釋放內存還會殺死系統進程。
swap 限制:
--memory-swap:只有在設置了 --memory 后才會有意義。使用 Swap,可以讓容器將超出限制部分的內存置換到磁盤上, WARNING:經常將內存交換到磁盤的應用程序會降低性能。
不同 --memory-swap 的設置會產生不同的效果:
值為正數, 那么--memory 和--memory-swap 都必須要設置, --memory-swap 表示你能使用的內存和 swap 分區大小的總和,例如: --memory=300m, --memory-swap=1g, 那么該容器能夠使用 300m 內存和 700m swap,即--memory 是實際物理內存大小值不變,而 swap 的實際大小計算方式為(--memory-swap)-(--memory)=容器可用 swap(??memory?swap)?(??memory)=容器可用swap。
如果設置為 0:則忽略該設置,并將該值視為未設置,即未設置交換分區。
如果等于--memory 的值,并且--memory 設置為正整數: 容器無權訪問 swap 即也沒有設置交換分區。
如果設置為 unset:如果宿主機開啟了 swap,則實際容器的swap 值為 2x( --memory),即兩倍于物理內存大小,但是并不準確(在容器中使用free 命令所看到的 swap 空間并不精確, 畢竟每個容器都可以看到具體大小,但是宿主機的 swap 是有上限而且不是所有容器看到的累計大小)。
如果設置為-1:如果宿主機開啟了 swap,則容器可以使用主機上 swap 的最大空間。
動態修改容器內存,先計算出所需要的內存的字節數:如268435456(256M),只能調大不能調小
echo "268435456" > /sys/fs/cgroup/memory/docker/9fa20d824b18.../memory.limit_in_bytes9fa20d824b18... 是容器ID
內存限制驗證:
假如一個容器未做內存使用限制, 則該容器可以利用到系統內存最大空間, 默認創建的容器沒有做內存資源限制。
#測試鏡像 docker pull lorel/docker-stress-ng ?查看幫助
apt install stress-ng stress-ng --help或者這樣也行
docker run -it --rm lorel/docker-stress-ng -help內存大小硬限制
查看docker狀態
docker stats --vm 啟動多少個進程
--vm-bytes 為每個進程分配的內存
宿主機基于 cgroup 對容器進行內存資源的大小限制
注:通過 echo 命令可以改內存限制的值,但是可以在原基礎之上增大內存限制,縮小內存限制會報錯 write error: Device or resource busy
內存大小軟限制:
docker run -it --rm -m 256m --memory-reservation 128m \--name c3 lorel/docker-stress-ng --vm 2 --vm-bytes 256M返回的軟限制結果
關閉 OOM 機制
docker run -it --rm -m 256m --oom-kill-disable \--name c4 lorel/dockerstress-ng --vm 2 --vm-bytes 256M # cat /sys/fs/cgroup/memory/docker/容器 ID/memory.oom_control oom_kill_disable 1 under_oom 1 oom_kill 0交換分區限制
docker run -it --rm -m 256m --memory-swap 512m \--name magedu-c1 centos bash宿主機 cgroup 驗證:
# cat /sys/fs/cgroup/memory/docker/容器 ID/memory.memsw.limit_in_bytes 536870912容器的 CPU 限制
一個宿主機,有幾十個核心的 CPU, 但是宿主機上可以同時運行成百上千個不同的進程用以處理不同的任務, 多進程共用一個 CPU 的核心依賴計數就是為可壓縮資源, 即一個核心的 CPU 可以通過調度而運行多個進程, 但是同一個單位時間內只能有一個進程在 CPU 上運行, 那么這么多的進程怎么在 CPU 上執行和調度的呢?
實時優先級: 0 - 99
非實時優先級(nice): -20 - 19, 對應 100 - 139 的進程優先級
Linux kernel 進程的調度基于 CFS(Completely Fair Scheduler), 完全公平調度
CPU 密集型的場景:優先級越低越好, 計算密集型任務的特點是要進行大量的計算,消耗 CPU 資源,比如計算圓周率、 數據處理、 對視頻進行高清解碼等等,全靠 CPU 的運算能力。
IO 密集型的場景:優先級值高點, 涉及到網絡、磁盤 IO 的任務都是 IO 密集型任務,這類任務的特點是 CPU 消耗很少,任務的大部分時間都在等待 IO 操作完成(因為 IO 的速度遠遠低于 CPU 和內存的速度),比如 Web 應用, 高并發,數據量大的動態網站來說,數據庫應該為 IO 密集型。
磁盤的調度算法
# cat /sys/block/sda/queue/scheduler noop deadline [cfq]默認情況下,每個容器對主機 CPU 周期的訪問權限是不受限制的, 但是我們可以設置各種約束來限制給定容器訪問主機的 CPU 周期,大多數用戶使用的是默認的 CFS 調度方式, 在 Docker 1.13 及更高版本中, 還可以配置實時優先級。
參數:
--cpus :指定容器可以使用多少可用 CPU 資源, 例如,如果主機有兩個 CPU,并且設置了--cpus =“1.5”,那么該容器將保證最多可以訪問 1.5 個的 CPU(如果是 4 核 CPU, 那么還可以是 4 核心上每核用一點,但是總計是 1.5 核心的CPU), 這相當于設置--cpu-period =“100000”和--cpu-quota =“150000”
主要在 Docker 1.13 和更高版本中使用, 目的是替代--cpu-period 和--cpuquota 兩個參數,從而使配置更簡單, 最大不能超出宿主機的 CPU 總核心數(在操作系統看到的 CPU 超線程后的數值)。
分配給容器的 CPU 超出了宿主機 CPU 總數。
# docker run -it --rm --cpus 2 centos bash docker: Error response from daemon: Range of CPUs is from 0.01 to 1.00, as there are only 1 CPUs available. See 'docker run --help'.--cpu-period:(CPU 調度周期)設置 CPU 的 CFS 調度程序周期,必須與--cpuquota 一起使用,默認周期為 100 微秒
--cpu-quota: 在容器上添加 CPU CFS 配額, 計算方式為 cpu-quota/cpu-period的結果值, 早期的 docker(1.12 及之前)使用此方式設置對容器的 CPU 限制值,==新版本 docker(1.13 及以上版本)通常使用--cpus 設置此值。==
--cpuset-cpus:用于指定容器運行的 CPU 編號,也就是我們所謂的綁核。
--cpuset-mem:設置使用哪個 cpu 的內存,僅對 非統一內存訪問(NUMA)架構有效。
--cpu-shares:用于設置 cfs 中調度的相對最大比例權重,cpu-share 的值越高的容器,將會分得更多的時間片(宿主機多核 CPU 總數為 100%, 假如容器 A 為1024, 容器 B 為 2048, 那么容器 B 將最大是容器 A 的可用 CPU 的兩倍 ),默認的時間片 1024,最大 262144。
測試 CPU 限制
對于一臺四核的服務器,如果不做限制, 容器會把宿主機的 CPU 全部占完。
分配 4 核 CPU 并啟動 4 個工作線程
在宿主機使用 dokcer top 命令查看容器運行狀態
docker top CONTAINER [ps OPTIONS]容器運行狀態:
docker stats在宿主機查看 CPU 限制參數:
# cat /sys/fs/cgroup/cpuset/docker/${容器ID}/cpuset.cpus 0-3只給容器分配最多兩核宿主機 CPU 利用率
宿主機 cgroup 驗證
# cat /sys/fs/cgroup/cpu,cpuacct/docker/容器 ID/cpu.cfs_quota_us 200000每核心 CPU 會按照 1000 為單位轉換成百分比進行資源劃分, 2 個核心的 CPU 就是 200000/1000=200%, 4 個核心 400000/1000=400%,以此類推
宿主機 CPU 利用率
容器運行狀態
docker stats啟動兩個容器, c13 的--cpu-shares?值為 1000, c14 的--cpu-shares為 500, 觀察最終效果,?--cpu-shares?值為 1000 的 c13 的 CPU 利用率基本是--cpu-shares?為 500 的 c14 的兩倍:
驗證容器運行狀態
docker stats宿主機 cgroup 驗證
# cat /sys/fs/cgroup/cpu,cpuacct/docker/容器 ID/cpu.shares 1000 # cat /sys/fs/cgroup/cpu,cpuacct/docker/容器 ID/cpu.shares 500驗證修改后的容器運行狀態? ? ?docker stats
十七
單機編排之Docker撰寫:
? ? 當在主機啟動主機的容器時候,如果都是手動操作會覺得比較麻煩而且容器出錯,這個時候推薦使用docker單機編排工具docker-compose,docker-compose是docker容器的一種單機編排服務,docker- compose是一個管理多個容器的工具,可以解決容器之間的依賴關系,就像啟動一個nginx前端服務的時候會調用后端的tomcat,那就得先啟動tomcat,但是啟動tomcat容器還需要依賴數據庫,則那就還得先啟動數據庫,docker-compose就可以解決這樣的嵌套依賴關系,其完全可以替代docker run對容器進行創建,啟動和停止。
docker-compose項目是Docker官方的開源項目,負責實現對Docker容器放置的快速編排,docker-compose將所管理的容器分為三層,分別是工程(項目),服務以及容器
github地址https://github.com/docker/compose
基礎環境準備:
服務器1 :192.168.99.21,港口服務器2:192.168.99.22, docker -compose 下面開始在服務器1上安裝harbor和創建nginx,tomcat,haproxy大量備用
配置安裝港口:
Ubuntu:
中心:
yum install epel-release yum install -y python-pip pip install --upgrade pip pip install docker-compose其中192.168.99.21是我們部署Harbor的地址,即hostname配置項值。配置完后需要重啟docker服務。
https://docs.docker.com/compose/reference/官方文檔
制作nginx鏡像
打標簽:
在港口管理界面創建項目(需要先創建項目再上傳高層)
將向前推到港口:
制作JDK環境
在港口頁面上創建jdk項目
將全面上傳到Harbor(以下有講)
從JDK整合重構tomcat
在港口頁面上創建tomcat項目
發布
構建tomcat-app業務運營:
制作haproxy補充:
調度到初步nginx服務的81端口
推送到倉庫
從docker compose啟動臨時容器
換成server2繼續:
下載docker-compose
Ubuntu:
Centos:
yum install epel-release yum install -y python-pip pip install --upgrade pip pip install docker-compose在ExecStart追加
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --insecure-registry 192.168.99.21編寫一個 yml 格式的配置 docker-compose 文件, 啟動一個 nginx 服務
service-nginx-web:服務名
image:鏡像名
container_name:容器名
expose:開放端口
post:宿主機映射端口
volume:數據卷掛載
不加是 d 前臺啟動
啟動多個容器
docker pull 192.168.99.21/tomcat/mytomcat-app:v1
重啟/停止/啟動單個指定容器
寫容器的 service 名稱,則是指定。
不指定則是所有
實現Nginx反向代理Tomcat
創建nginx配置文件
# '"http_user_agent" "http_x_forwarded_for"';
# access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on; upstream tomcat_webserver {
server service-tomcat-app1:8080;
server service-tomcat-app2:8080;
}
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location /app1 {
root /apps/nginx/html;
index index.html index.htm;
}
location /app2 {
root /apps/nginx/html;
index index.html index.htm;
}
location /tomcat-app {
proxy_pass http://tomcat_webserver;
proxy_set_header Host host;proxy_set_header X-Forwarded-For proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP remote_addr;}#error_page 404 /404.html;# redirect server error pages to the static page /50x.html#error_page 500 502 503 504 /50x.html;location = /50x.html {root html;}} }
創建haproxy配置文件
cd /opt/app mkdir -p haproxy/confvim ./haproxy/conf/haproxy.cfg
globalchroot /usr/local/haproxyuid 99gid 99daemonnbproc 1pidfile /usr/local/haproxy/run/haproxy.pidlog 127.0.0.1 local3 infodefaultsoption http-keep-aliveoption forwardformode httptimeout connect 300000mstimeout client 300000mstimeout server 300000mslisten statsmode httpbind 0.0.0.0:9999stats enablelog globalstats uri /haproxy-statusstats auth admin:123listen web_portbind 0.0.0.0:80mode httplog globalbalance roundrobinserver web1 nginx-web1:80 check inter 3000 fall 2 rise 5
nginx-web1:80 這里寫的是容器內部的端口,所以nginx容器開放的什么端口就寫多少,默認80。因為沒有對宿主機映射,所以可以不會端口沖突。
nginx-web1 是容器名
準備tomcat配置文件
cd /opt/app mkdir -p tomcat/conf vim tomcat/conf/server.xml <?xml version="1.0" encoding="UTF-8"?> <!--Licensed to the Apache Software Foundation (ASF) under one or morecontributor license agreements. See the NOTICE file distributed withthis work for additional information regarding copyright ownership.The ASF licenses this file to You under the Apache License, Version 2.0(the "License"); you may not use this file except in compliance withthe License. You may obtain a copy of the License athttp://www.apache.org/licenses/LICENSE-2.0Unless required by applicable law or agreed to in writing, softwaredistributed under the License is distributed on an "AS IS" BASIS,WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.See the License for the specific language governing permissions andlimitations under the License. --> <!-- Note: A "Server" is not itself a "Container", so you may notdefine subcomponents such as "Valves" at this level.Documentation at /docs/config/server.html--> <Server port="8005" shutdown="SHUTDOWN"><Listener className="org.apache.catalina.startup.VersionLoggerListener" /><!-- Security listener. Documentation at /docs/config/listeners.html<Listener className="org.apache.catalina.security.SecurityListener" />--><!--APR library loader. Documentation at /docs/apr.html --><Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" /><!-- Prevent memory leaks due to use of particular java/javax APIs--><Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" /><Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" /><Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" /><!-- Global JNDI resourcesDocumentation at /docs/jndi-resources-howto.html--><GlobalNamingResources><!-- Editable user database that can also be used byUserDatabaseRealm to authenticate users--><Resource name="UserDatabase" auth="Container"type="org.apache.catalina.UserDatabase"description="User database that can be updated and saved"factory="org.apache.catalina.users.MemoryUserDatabaseFactory"pathname="conf/tomcat-users.xml" /></GlobalNamingResources><!-- A "Service" is a collection of one or more "Connectors" that sharea single "Container" Note: A "Service" is not itself a "Container",so you may not define subcomponents such as "Valves" at this level.Documentation at /docs/config/service.html--><Service name="Catalina"><!--The connectors can use a shared executor, you can define one or more named thread pools--><!--<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"maxThreads="150" minSpareThreads="4"/>--><!-- A "Connector" represents an endpoint by which requests are receivedand responses are returned. Documentation at :Java HTTP Connector: /docs/config/http.htmlJava AJP Connector: /docs/config/ajp.htmlAPR (HTTP/AJP) Connector: /docs/apr.htmlDefine a non-SSL/TLS HTTP/1.1 Connector on port 8080--><Connector port="8080" protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443" /><!-- A "Connector" using the shared thread pool--><!--<Connector executor="tomcatThreadPool"port="8080" protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443" />--><!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443This connector uses the NIO implementation. The defaultSSLImplementation will depend on the presence of the APR/nativelibrary and the useOpenSSL attribute of theAprLifecycleListener.Either JSSE or OpenSSL style configuration may be used regardless ofthe SSLImplementation selected. JSSE style configuration is used below.--><!--<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"maxThreads="150" SSLEnabled="true"><SSLHostConfig><Certificate certificateKeystoreFile="conf/localhost-rsa.jks"type="RSA" /></SSLHostConfig></Connector>--><!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443 with HTTP/2This connector uses the APR/native implementation which always usesOpenSSL for TLS.Either JSSE or OpenSSL style configuration may be used. OpenSSL styleconfiguration is used below.--><!--<Connector port="8443" protocol="org.apache.coyote.http11.Http11AprProtocol"maxThreads="150" SSLEnabled="true" ><UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" /><SSLHostConfig><Certificate certificateKeyFile="conf/localhost-rsa-key.pem"certificateFile="conf/localhost-rsa-cert.pem"certificateChainFile="conf/localhost-rsa-chain.pem"type="RSA" /></SSLHostConfig></Connector>--><!-- Define an AJP 1.3 Connector on port 8009 --><Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /><!-- An Engine represents the entry point (within Catalina) that processesevery request. The Engine implementation for Tomcat stand aloneanalyzes the HTTP headers included with the request, and passes themon to the appropriate Host (virtual host).Documentation at /docs/config/engine.html --><!-- You should set jvmRoute to support load-balancing via AJP ie :<Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">--><Engine name="Catalina" defaultHost="localhost"><!--For clustering, please take a look at documentation at:/docs/cluster-howto.html (simple how to)/docs/config/cluster.html (reference documentation) --><!--<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>--><!-- Use the LockOutRealm to prevent attempts to guess user passwordsvia a brute-force attack --><Realm className="org.apache.catalina.realm.LockOutRealm"><!-- This Realm uses the UserDatabase configured in the global JNDIresources under the key "UserDatabase". Any editsthat are performed against this UserDatabase are immediatelyavailable for use by the Realm. --><Realm className="org.apache.catalina.realm.UserDatabaseRealm"resourceName="UserDatabase"/></Realm><Host name="localhost" appBase="/data/tomcat/webapps/app"unpackWARs="true" autoDeploy="true"><!-- SingleSignOn valve, share authentication between web applicationsDocumentation at: /docs/config/valve.html --><!--<Valve className="org.apache.catalina.authenticator.SingleSignOn" />--><!-- Access log processes all example.Documentation at: /docs/config/valve.htmlNote: The pattern used is equivalent to using pattern="common" --><Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"prefix="localhost_access_log" suffix=".txt"pattern="%h %l %u %t "%r" %s %b" /></Host></Engine></Service> </Server>注意這里:因為nginx中位置配置的配置路徑是tomcat-app,往tomcat調度的時候會帶上這個路徑,所以,掛載進去的路徑也要與之匹配。即:要能夠訪問http:// tomcat -app1:8080 / tomcat-app,才能通過nginx來調度
創建docker-compose.yml
mkdir -p /opt/app cd /opt/app vim docker-compose.yml service-haproxy:image: 192.168.99.21/haproxy/haproxy:v1container_name: haproxyvolumes:- ./haproxy/conf/haproxy.cfg:/etc/haproxy/haproxy.cfgexpose:- 80- 443- 9999ports:- "80:80"- "443:443"- "9999:9999"links:- service-nginx-webservice-nginx-web:image: 192.168.99.21/nginx/mynginx:v1container_name: nginx-web1volumes:- ./nginx/html/app1:/apps/nginx/html/app1- ./nginx/html/app2:/apps/nginx/html/app2- ./nginx/conf/nginx.conf:/usr/local/nginx/conf/nginx.confexpose:- 80- 443links:- service-tomcat-app1- service-tomcat-app2service-tomcat-app1:image: 192.168.99.21/tomcat/mytomcat-app:v1container_name: tomcat-app1volumes:- ./tomcat/app1:/data/tomcat/webapps/app/ROOT- ./tomcat/conf/server.xml:/apps/tomcat/conf/server.xmlexpose:- 8080service-tomcat-app2:image: 192.168.99.21/tomcat/mytomcat-app:v1container_name: tomcat-app2volumes:- ./tomcat/app1:/data/tomcat/webapps/app/ROOT- ./tomcat/conf/server.xml:/apps/tomcat/conf/server.xmlexpose:- 8080最終文件目錄
cd /opt/app # tree . ├── docker-compose.yml ├── haproxy │ └── conf │ └── haproxy.cfg │ ├── nginx │ ├── conf │ │ └── nginx.conf │ └── html │ ├── app1 │ │ └── index.html │ └── app2 │ └── index.html └── tomcat├── app1│ └── tomcat-app│ └── showhost.jsp└── conf└── server.xml測試訪問
http://192.168.99.22/tomcat-app/showhost.jsp
以上就是Docke容器大部分的使用情景及功能實現
總結
以上是生活随笔為你收集整理的centos安装Docker与使用构建业务镜像挂载卷harbor仓库的高可用及网络模式和资源限制介绍...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 华为m2android怎么升级,【刷机指
- 下一篇: 利用Cookie显示上次登录时间