防偽碼:梅須遜雪三分白,雪卻輸梅一段香
docker技術(shù)剖析--dockerfile and registry(構(gòu)建容器和私有倉庫)
一、根據(jù)Dockerfile構(gòu)建出一個容器
1、Dockfile是一種被Docker程序解釋的腳本,Dockerfile由一條一條的指令組成,每條指令對應(yīng)Linux下面的一條命令。Docker程序?qū)⑦@些Dockerfile指令翻譯真正的Linux命令。Dockerfile有自己書寫格式和支持的命令,Docker程序解決這些命令間的依賴關(guān)系,類似于Makefile。2、Docker程序?qū)⒆x取Dockerfile,根據(jù)指令生成定制的image。相比image這種黑盒子,Dockerfile這種顯而易見的腳本更容易被使用者接受,它明確的表明image是怎么產(chǎn)生的。有了Dockerfile,當(dāng)我們需要定制自己額外的需求時,只需在Dockerfile上添加或者修改指令,重新生成image即可,省去了敲命令的麻煩。
3、Dockerfile由一行行命令語句組成,并且支持以 # 開頭的注釋行。
4、Dockerfile的指令是忽略大小寫的,建議使用大寫,每一行只支持一條指令,每條指令可以攜帶多個參數(shù)。
5、Dockerfile的指令根據(jù)作用可以分為兩種,構(gòu)建指令和設(shè)置指令。構(gòu)建指令用于構(gòu)建image,其指定的操作不會在運行image的容器上執(zhí)行;設(shè)置指令用于設(shè)置image的屬性,其指定的操作將在運行image的容器中執(zhí)行。
一般的,Dockerfile分為四部分:基礎(chǔ)鏡像信息、維護者信息、鏡像操作指令和容器啟動時執(zhí)行指令。
# Thisdockerfile uses the ubuntu image
# VERSION 2 - EDITION 1
# Author: docker_user
# Command format: Instruction [arguments / command] ..
# Base image to use, this must be set as the first line
FROM ubuntu
# Maintainer: docker_user<docker_user at email.com> (@docker_user)
MAINTAINER docker_user docker_user@email.com
# Commands to update the image
RUN echo "deb http://archive.ubuntu.com/ubuntu/ raring main universe" >> /etc/apt/sources.list
RUN apt-get update && apt-get install -y nginx
RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf
# Commands when creating a new container
CMD /usr/sbin/nginx
其中,一開始必須指明所基于的鏡像名稱,接下來推薦說明維護者信息。
后面則是鏡像操作指令,例如 RUN 指令, RUN 指令將對鏡像執(zhí)行跟隨的命令。每運行一條 RUN 指令,鏡像添加新的一層,并提交。
最后是 CMD 指令,來指定運行容器時的操作命令。
dockerfile指令
指令的一般格式為 INSTRUCTION arguments ,指令包括 FROM 、 MAINTAINER 、 RUN 等。
(1)FROM(指定基礎(chǔ)image)
構(gòu)建指令,必須指定且需要在Dockerfile其他指令的前面。后續(xù)的指令都依賴于該指令指定的image。FROM指令指定的基礎(chǔ)image可以是官方遠程倉庫中的,也可以位于本地倉庫。
該指令有兩種格式:
FROM <image>
指定基礎(chǔ)image為該image的最后修改的版本。
或者:
FROM <image>:<tag>
指定基礎(chǔ)image為該image的一個tag版本。
(2)MAINTAINER(用來指定鏡像創(chuàng)建者信息)
構(gòu)建指令,用于將image的制作者相關(guān)的信息寫入到image中。當(dāng)我們對該image執(zhí)行docker
inspect命令時,輸出中有相應(yīng)的字段記錄該信息。
格式:
MAINTAINER <name>
(3)RUN(安裝軟件用)
構(gòu)建指令,RUN可以運行任何被基礎(chǔ)image支持的命令。如基礎(chǔ)image選擇了ubuntu,那么軟件管理部分只能使用ubuntu的命令。
該指令有兩種格式:
RUN <command> (the command is run in a shell - `/bin/sh -c`)
RUN ["executable", "param1", "param2" ... ] (exec form)
前者將在 shell 終端中運行命令,即 /bin/sh -c ;后者則使用 exec 執(zhí)行。
指定使用其它終端可以通過第二種方式實現(xiàn),例如 RUN ["/bin/bash", "-c", "echo hello"] 。
每條 RUN 指令將在當(dāng)前鏡像基礎(chǔ)上執(zhí)行指定命令,并提交為新的鏡像。當(dāng)命令較長時可以使用 \ 來換行。
(4)CMD(設(shè)置container啟動時執(zhí)行的操作)
該指令有三種格式:
設(shè)置指令,用于container啟動時指定的操作。該操作可以是執(zhí)行自定義腳本,也可以是執(zhí)行系統(tǒng)命令。
CMD ["executable","param1","param2"] 使用 exec 執(zhí)行,推薦方式;
CMD command param1 param2 在 /bin/sh中執(zhí)行,提供給需要交互的應(yīng)用;
當(dāng)Dockerfile指定了ENTRYPOINT,那么使用下面的格式:
CMD ["param1","param2"] 提供給 ENTRYPOINT 的默認參數(shù);
ENTRYPOINT指定的是一個可執(zhí)行的腳本或者程序的路徑,該指定的腳本或者程序?qū)詐aram1和param2作為參數(shù)執(zhí)行。所以如果CMD指令使用上面的形式,那么Dockerfile中必須要有配套的ENTRYPOINT。
指定啟動容器時執(zhí)行的命令,每個Dockerfile只能有一條 CMD 命令。如果指定了多條命令,只有最后一條會被執(zhí)行。
如果用戶啟動容器時候指定了運行的命令,則會覆蓋掉 CMD 指定的命令。
(5)ENTRYPOINT(設(shè)置container啟動時執(zhí)行的操作)
設(shè)置指令,指定容器啟動時執(zhí)行的命令,可以多次設(shè)置,但是只有最后一個有效。
兩種格式:
ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2 (shell中執(zhí)行)。
配置容器啟動后執(zhí)行的命令,并且不可被 docker run 提供的參數(shù)覆蓋。
每個 Dockerfile 中只能有一個 ENTRYPOINT ,當(dāng)指定多個時,只有最后一個起效。
該指令的使用分為兩種情況,一種是獨自使用,另一種和CMD指令配合使用。
當(dāng)獨自使用時,如果你還使用了CMD命令且CMD是一個完整的可執(zhí)行的命令,那么CMD指令和ENTRYPOINT會互相覆蓋只有最后一個CMD或者ENTRYPOINT有效。
例如:CMD指令將不會被執(zhí)行,只有ENTRYPOINT指令被執(zhí)行
CMD echo “Hello, World!”
ENTRYPOINT ls -l
另一種用法和CMD指令配合使用來指定ENTRYPOINT的默認參數(shù),這時CMD指令不是一個完整的可執(zhí)行命令,僅僅是參數(shù)部分;ENTRYPOINT指令只能使用JSON方式指定執(zhí)行命令,而不能指定參數(shù)。
例如
FROM ubuntu
CMD ["-l"]
ENTRYPOINT ["/usr/bin/ls"]
(6)USER(設(shè)置container容器的用戶,默認是root用戶)
格式為 USER daemon
指定運行容器時的用戶名或 UID,后續(xù)的 RUN 也會使用指定用戶。
當(dāng)服務(wù)不需要管理員權(quán)限時,可以通過該命令指定運行用戶。并且可以在之前創(chuàng)建所需要的用戶,例
如: RUN groupadd -r postgres&&useradd -r -g postgrespostgres
例如: 指定memcached的運行用戶
ENTRYPOINT ["memcached"]
USER daemon
或
ENTRYPOINT ["memcached", "-u", "daemon"]
(7)EXPOSE(指定容器需要映射到宿主機器的端口)
格式為 EXPOSE <port> [<port>...]
設(shè)置指令,該指令會將容器中的端口映射成宿主機器中的某個端口。當(dāng)你需要訪問容器的時候,可以不是用容器的IP地址而是使用宿主機器的IP地址和映射后的端口。
要完成整個操作需要兩個步驟,首先在Dockerfile使用EXPOSE設(shè)置需要映射的容器端口,然后在運行容器的時候指定-p選項加上EXPOSE設(shè)置的端口,這樣EXPOSE設(shè)置的端口號會被隨機映射成宿主機器中的一個端口號。也可以指定需要映射到宿主機器的那個端口,這時要確保宿主機器上的端口號沒有被使用。EXPOSE指令可以一次設(shè)置多個端口號,相應(yīng)的運行容器的時候,可以配套的多次使用-p選項。
例如: 映射一個端口
EXPOSE port1
# 相應(yīng)的運行容器使用的命令
docker run -p port1 image
例如: 映射多個端口
EXPOSE port1 port2 port3
# 相應(yīng)的運行容器使用的命令
docker run -p port1 -p port2 -p port3 image
# 還可以指定需要映射到宿主機器上的某個端口號
docker run -p host_port1:port1 -p host_port2:port2 -p host_port3:port3 image
端口映射是docker比較重要的一個功能,原因在于我們每次運行容器的時候容器的IP地址不能指定而是在橋接網(wǎng)卡的地址范圍內(nèi)隨機生成的。宿主機器的IP地址是固定的,我們可以將容器的端口的映射到宿主機器上的一個端口,免去每次訪問容器中的某個服務(wù)時都要查看容器的IP的地址。
對于一個運行的容器,可以使用docker port加上容器中需要映射的端口和容器的ID來查看該端口號在宿主機器上的映射端口
(8)ENV(用于設(shè)置環(huán)境變量)
構(gòu)建指令,指定一個環(huán)境變量,會被后續(xù) RUN 指令使用,并在容器運行時保持。
格式:
ENV <key> <value>
設(shè)置了后,后續(xù)的RUN命令都可以使用,container啟動后,可以通過docker
inspect查看這個環(huán)境變量,也可以通過在docker run --env key=value時設(shè)置或修改環(huán)境變量。
假如你安裝了JAVA程序,需要設(shè)置JAVA_HOME,那么可以在Dockerfile中這樣寫:ENV JAVA_HOME /path/to/java/dirent
再例如:
ENV PG_MAJOR 9.3
ENV PG_VERSION 9.3.4
RUN curl http://example.com/postgres-$PG_VERSION.tar.xz | tar -xJC /usr/src/postgress
ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH
(9)ADD(從src復(fù)制文件到container的dest路徑)
構(gòu)建指令,所有拷貝到container中的文件和文件夾權(quán)限為0755,uid和gid為0;
如果是一個目錄,那么會將該目錄下的所有文件添加到container中,不包括目錄;
如果文件是可識別的壓縮格式,則docker會幫忙解壓縮(注意壓縮格式);
如果<src>是文件且<dest>中不使用斜杠結(jié)束,則會將<dest>視為文件,<src>的內(nèi)容會寫入<dest>;
如果<src>是文件且<dest>中使用斜杠結(jié)束,則會<src>文件拷貝到<dest>目錄下。
格式:
ADD <src> <dest>
該命令將復(fù)制指定的<src>到容器中的<dest>。
其中<src>可以是Dockerfile所在目錄的一個相對路徑;也可以是一個 URL;還可以是一個 tar 文件(自動解壓為目錄)
<dest>是container中的絕對路徑(10)COPY
格式為 COPY <src><dest>
復(fù)制本地主機的<src>(為Dockerfile所在目錄的相對路徑)到容器中的<dest>。
(11)VOLUME(指定掛載點)
設(shè)置指令,使容器中的一個目錄具有持久化存儲數(shù)據(jù)的功能,該目錄可以被容器本身使用,也可以共享給其他容器使用。我們知道容器使用的是AUFS,這種文件系統(tǒng)不能持久化數(shù)據(jù),當(dāng)容器關(guān)閉后,所有的更改都會丟失。當(dāng)容器中的應(yīng)用有持久化數(shù)據(jù)的需求時可以在Dockerfile中使用該指令。
格式:
VOLUME ["<mountpoint>"]
例如:FROM base
VOLUME ["/tmp/data"]
運行通過該Dockerfile生成image的容器,/tmp/data目錄中的數(shù)據(jù)在容器關(guān)閉后,里面的數(shù)據(jù)還存在。例如另一個容器也有持久化數(shù)據(jù)的需求,且想使用上面容器共享的/tmp/data目錄,那么可以運行下面的命令啟動一個容器:
docker run -t -i -rm -volumes-from container1 image2 bash
container1為第一個容器的ID,image2為第二個容器運行image的名字。
(12)WORKDIR(切換目錄)
設(shè)置指令,可以多次切換(相當(dāng)于cd命令),對RUN,CMD,ENTRYPOINT生效。為后續(xù)的 RUN、CMD、ENTRYPOINT 指令配置工作目錄。
格式:
WORKDIR /path/to/workdir
例如: 在 /p1/p2 下執(zhí)行 vim a.txt
WORKDIR /p1
WORKDIR p2
RUN vim a.txt
可以使用多個 WORKDIR 指令,后續(xù)命令如果參數(shù)是相對路徑,則會基于之前命令指定的路徑。
例如
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
則最終路徑為 /a/b/c 。
(13)ONBUILD(在子鏡像中執(zhí)行)
ONBUILD <Dockerfile關(guān)鍵字>
ONBUILD 指定的命令在構(gòu)建鏡像時并不執(zhí)行,而是在它的子鏡像中執(zhí)行。
格式為 ONBUILD [INSTRUCTION] 。
配置當(dāng)所創(chuàng)建的鏡像作為其它新創(chuàng)建鏡像的基礎(chǔ)鏡像時,所執(zhí)行的操作指令。
例如,Dockerfile使用如下的內(nèi)容創(chuàng)建了鏡像 image-A 。
[...]
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
[...]
如果基于 image-A 創(chuàng)建新的鏡像時,新的Dockerfile中使用 FROM image-A 指定基礎(chǔ)鏡像時,會自動執(zhí)行ONBUILD 指令內(nèi)容。
等價于在后面添加了兩條指令。
FROM image-A
#Automatically run the following
ADD . /app/src
RUN /usr/local/bin/python-build --dir /app/src
使用 ONBUILD 指令的鏡像,推薦在標(biāo)簽中注明,例如 ruby:1.9-onbuild 。
編寫完成Dockerfile之后,可以通過docker build 命令來創(chuàng)建鏡像。
基本的格式為docker build [選項] 路徑,該命令將讀取指定路徑下的Dockerfile,并將該路徑下所有內(nèi)容發(fā)送給 Docker 服務(wù)端,由服務(wù)端來創(chuàng)建鏡像。因此一般建議放置Dockerfile的目錄為空目錄。
要指定鏡像的標(biāo)簽信息,可以通過 -t 選項,例如
$ sudodocker build –tmyrepo/myapp/tmp/test1/
1) 創(chuàng)建一個sshd_dockerfile工作目錄
編輯run.sh文件
在主機上生成ssh秘鑰對,并創(chuàng)建authorized_keys文件
2) 編寫Dockerfile
FROM docker.io/centos:centos6
MAINTAINER from yw@example.com
RUN yum install -q -y httpd openssh-server sudo
RUN useradd admin
RUN echo "admin:admin" | chpasswd
RUN echo "admin ALL=(ALL) ALL" >> /etc/sudoers
RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
RUN mkdir -p /var/run/sshd
RUN mkdir -p /home/admin/.ssh
RUN sed -ri 's/#ServerName www.example.com:80/ServerName www.benet.com/g' /etc/httpd/conf/httpd.conf
ADD authorized_keys /home/admin/.ssh/authorized_keys
ADD run.sh /run.sh
RUN chmod 775 /run.sh
EXPOSE 22 80
CMD ["/run.sh"]
以上選項的含義解釋:
FROM centos:centos6選擇一個已有的os鏡像作為基礎(chǔ)
MAINTAINER 鏡像的作者
RUN yum install -y openssh-server sudo安裝openssh-server和sudo軟件包
添加測試用戶admin,密碼admin,并且將此用戶添加到sudoers里
RUN useradd admin
RUN echo "admin:admin" | chpasswd
RUN echo "admin ALL=(ALL) ALL" >> /etc/sudoers
下面這兩句比較特殊,在centos6上必須要有,否則創(chuàng)建出來的容器sshd不能登錄
RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
注意:centos7上必須要有,否則創(chuàng)建出來的容器sshd不能登錄
RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
RUN ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key
RUN ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key
將公鑰信息上傳到遠程連接用戶的宿主目錄的.ssh下
ADD authorized_keys /home/admin/.ssh/authorized_keys
啟動sshd服務(wù)并且暴露22端口
RUN mkdir /var/run/sshd
EXPOSE 22 80
CMD ["/run.sh"] 也可以寫成這種方式CMD ["/usr/sbin/sshd", "-D"]
在sshd_dockerfile目錄下,使用docker build命令來創(chuàng)建鏡像,注意:在最后還有一個”.”,表示使用當(dāng)前目錄中的dockerfile
[root@localhost sshd_dockerfile]# docker build --no-cache -t "centos:httpdv1" .
Sending build context to Docker daemon 4.608 kB
Step 1 : FROM docker.io/centos:centos6
---> cf2c3ece5e41
Step 2 : MAINTAINER from yw@example.com
---> Running in 02bd0437a4b1
---> 5c8b8cf12528
Removing intermediate container 02bd0437a4b1
Step 3 : RUN yum install -q -y httpd openssh-server sudo
---> Running in cac5c0661e31
install-info: No such file or directory for /usr/share/info/ipc.info
---> 8217526950c1
Removing intermediate container cac5c0661e31
Step 4 : RUN useradd admin
---> Running in 9f067575fcc5
---> 434a46a9d9b7
Removing intermediate container 9f067575fcc5
Step 5 : RUN echo "admin:admin" | chpasswd
---> Running in 4fc098b1944f
---> 9b30d92cc2f8
Removing intermediate container 4fc098b1944f
Step 6 : RUN echo "admin ALL=(ALL) ALL" >> /etc/sudoers
---> Running in cf449db4e8b0
---> 958c58e8cf3e
Removing intermediate container cf449db4e8b0
Step 7 : RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key
---> Running in c07dfc40de6a
ing public/private dsa key pair.
Your identification has been saved in /etc/ssh/ssh_host_dsa_key.
Your public key has been saved in /etc/ssh/ssh_host_dsa_key.pub.
The key fingerprint is:
65:2e:34:e9:28:2e:05:cc:e3:cd:b9:56:f1:74:0a:78 root@68a1f3cfce80
The key's randomart image is:
+--[ DSA 1024]----+
| |
| o . . |
| = . E = + |
| . = o O B |
| . * o S . |
| o + . |
| . + |
| o |
| |
+-----------------+
---> c71b15053329
Removing intermediate container c07dfc40de6a
Step 8 : RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
---> Running in 22f89e60e3cb
Enter passphrase (empty for no passphrase): Enter same passphrase again: Generating public/private rsa key pair.
Your identification has been saved in /etc/ssh/ssh_host_rsa_key.
Your public key has been saved in /etc/ssh/ssh_host_rsa_key.pub.
The key fingerprint is:
d2:e2:db:8a:8c:f1:31:97:c9:0a:f3:27:0d:75:b4:5b root@68a1f3cfce80
The key's randomart image is:
+--[ RSA 2048]----+
| |
| . |
| . . |
| ..o E |
| .o.So |
| .o =. |
| + oo* |
| O.*oo |
| . *oo.. |
+-----------------+
---> 85934eb336c0
Removing intermediate container 22f89e60e3cb
Step 9 : RUN mkdir -p /var/run/sshd
---> Running in 4283e5fd0df5
---> aa73493a7bd3
Removing intermediate container 4283e5fd0df5
Step 10 : RUN mkdir -p /home/admin/.ssh
---> Running in a93eaa720d85
---> 60d9caed6257
Removing intermediate container a93eaa720d85
Step 11 : RUN sed -ri 's/#ServerName www.example.com:80/ServerName www.benet.com/g' /etc/httpd/conf/httpd.conf
---> Running in bb990d411b95
---> 5dd27b1ecc3a
Removing intermediate container bb990d411b95
Step 12 : ADD authorized_keys /home/admin/.ssh/authorized_keys
---> 44331f21246d
Removing intermediate container b49ac6ccebc6
Step 13 : ADD run.sh /run.sh
---> fbac25942581
Removing intermediate container 8a199cee60e9
Step 14 : RUN chmod 775 /run.sh
---> Running in c16e98e92af0
---> bc7b3a62bbf6
Removing intermediate container c16e98e92af0
Step 15 : EXPOSE 22 80
---> Running in 02a15849100c
---> 9687385e5a06
Removing intermediate container 02a15849100c
Step 16 : CMD /run.sh
---> Running in eb5f59e85ed9
---> d95ea0e3fb37
Removing intermediate container eb5f59e85ed9
Successfully built d95ea0e3fb37
執(zhí)行docker images查看新生成的鏡像
[root@localhost ~]# docker images
使用剛才建好的鏡像運行一個容器,將容器的端口映射到主機的10122
[root@localhost ~]# docker run -dit --name webserver1 -p 10122:22 -p 80:80 --restart=always centos:httpdv1
[root@localhost ~]# docker ps
在宿主主機打開一個終端,連接剛才新建的容器
注:admin用戶是容器中的用戶,192.168.152.142是宿主機的地址。
測試sudo執(zhí)行授權(quán)命令:
或
用docker inspect查看容器的ip地址,在宿主機上直接ssh連接容器
二、Docker倉庫
倉庫(Repository)是集中存放鏡像的地方。
一個容易混淆的概念是注冊服務(wù)器(Registry)。實際上注冊服務(wù)器是管理倉庫的具體服務(wù)器,每個服務(wù)器上可以有多個倉庫,而每個倉庫下面有多個鏡像。從這方面來說,倉庫可以被認為是一個具體的項目或目錄。例如對于倉庫地址 docker.sina.com.cn/centos:centos63 來說,docker.sina.com.cn 是注冊服務(wù)器地址,centos 是倉庫名,centos6是倉庫的 tag。
Docker Hub 官方倉庫
目前 Docker 官方維護了一個公共倉庫 Docker Hub,其中已經(jīng)包括了超過 15,000 的鏡像。大部分需求,都可以通過在 Docker Hub 中直接下載鏡像來實現(xiàn)。
注冊&登錄
可以通過命令行執(zhí)行docker login 命令來輸入用戶名、密碼和郵箱來完成注冊和登錄。注冊成功后,本地用戶目錄的 .docker/config.json中將保存用戶的認證信息。
基本操作
用戶無需登錄即可通過docker search 命令來查找官方倉庫中的鏡像,并利用docker pull 命令來將它下載到本地。
例如以 centos 為關(guān)鍵詞進行搜索:
可以看到返回了很多包含關(guān)鍵字的鏡像,其中包括鏡像名字、描述、星級(表示該鏡像的受歡迎程度)、是否官方創(chuàng)建、是否自動創(chuàng)建。官方的鏡像說明是官方項目組創(chuàng)建和維護的,automated 資源允許用戶驗證鏡像的來源和內(nèi)容。
根據(jù)是否是官方提供,可將鏡像資源分為兩類。一種是類似 centos 這樣的基礎(chǔ)鏡像,被稱為基礎(chǔ)或根鏡像。這些基礎(chǔ)鏡像是由 Docker 公司創(chuàng)建、驗證、支持、提供。這樣的鏡像往往使用單個單詞作為名字。還有一種類型,比如tianon/centos 鏡像,它是由 Docker 的用戶創(chuàng)建并維護的,往往帶有用戶名稱前綴。可以通過前綴user_name/ 來指定使用某個用戶提供的鏡像,比如tianon用戶。另外,在查找的時候通過 -s N 參數(shù)可以指定僅顯示評價為 N 星以上的鏡像。
創(chuàng)建自己的倉庫----鏡像倉庫
拓撲:
說明:
docker.benet.com 這是docker registry服務(wù)器的主機名稱,ip是192.168.1.107;因為https的SSL證書要用到主機名,所以要設(shè)置主機名。
dockerregistry 服務(wù)器作為處理docker鏡像的最終上傳和下載,用的是官方的鏡像registry。
nginx 1.6.x 是一個用nginx作為反向代理服務(wù)器
注:關(guān)閉selinux
1)私有倉庫https支持:
A)安裝依賴軟件包:
在Nginx編譯需要PCRE,因為Nginx的Rewrite模塊和HTTP核心模塊會使用到PCRE正則表達式。需要安裝pcre和pcre-devel用yum就能安裝。
Zlib庫提供了開發(fā)人員的壓縮算法,在nginx的模塊中需要使用gzip壓縮。
需要安裝zlib和zlib-devel用yum就可以安裝
在Nginx中如果需要為服務(wù)器提供安全則需要用到OpenSSL庫。
需要安裝的是openssl和openssl-devel。用yum就可以安裝。
B)配置SSL
(1) 編輯/etc/hosts,把docker.benet.com的ip地址添加進來,例如:
主機名、ip地址:
/etc/hosts文件內(nèi)容:
(2) 生成根密鑰(使用xshell完成操作)
先把
/etc/pki/CA/cacert.pem
/etc/pki/CA/index.txt
/etc/pki/CA/index.txt.attr
/etc/pki/CA/index.txt.old
/etc/pki/CA/serial
/etc/pki/CA/serial.old
刪除掉!
(3) 生成根證書
執(zhí)行
輸出如下信息
會提示輸入一些內(nèi)容,因為是私有的,所以可以隨便輸入,最好記住能與后面保持一致,特別是"Common Name”。必須要和hostname顯示的一致。
上面的自簽證書cacert.pem應(yīng)該生成在/etc/pki/CA下。
(4) 為nginx web服務(wù)器生成ssl密鑰
注:因為CA中心與要申請證書的nginx服務(wù)器是同一個所以就在本機上執(zhí)行為nginx服務(wù)器生成ssl密鑰了,否則應(yīng)該是在另一臺需要用到證書的服務(wù)器上生成。
查看nginx服務(wù)器的密鑰
(5) 為nginx生成證書簽署請求
執(zhí)行
openssl req -new -key nginx.key -out nginx.csr
輸出如下信息
同樣會提示輸入一些內(nèi)容,Commone Name一定要是你要授予證書的服務(wù)器域名或主機名,challenge password不填。
(6) 私有CA根據(jù)請求來簽發(fā)證書
執(zhí)行
openssl ca -in nginx.csr -out nginx.crt
輸出內(nèi)容:
同樣會提示輸入一些內(nèi)容,選擇y就可以了!
查看nginx的證書
C)安裝,配置,運行nginx
(1) 添加組和用戶
(2) 下載nginx源文件:
wget http://nginx.org/download/nginx-1.11.2.tar.gz
(3) 編譯,安裝nginx:
上述選項的解釋:
--user=USER 設(shè)定程序運行的用戶環(huán)境(www)
--group=GROUP 設(shè)定程序運行的組環(huán)境(www)
--prefix=PATH 設(shè)定安裝目錄
--with-pcre啟用pcre庫,Nginx的Rewrite模塊和HTTP核心模塊會使用到PCRE正則表達式
--with-http_stub_status_module 是為了啟用 nginx 的 NginxStatus 功能,用來監(jiān)控 Nginx 的當(dāng)前狀態(tài)
--with-http_ssl_module 開啟SSL模塊,支持使用HTTPS協(xié)議的網(wǎng)頁
--with-http_realip_module 開啟Real IP的支持,該模塊用于從客戶請求的頭數(shù)據(jù)中讀取Real Ip地址
--with-http_addition_module 開啟Addtion模塊,該模塊允許你追加或前置數(shù)據(jù)到相應(yīng)的主體部分
--with-http_flv_module模塊ngx_http_flv_module 為Flash Video(FLV)文件提供服務(wù)端偽流媒體支持
make && make install
(4) 編輯/opt/nginx/conf/nginx.conf文件
user www;
worker_processes 4;
events {
worker_connections 4096;
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream registry {
server 192.168.1.107:5000;
}
server {
listen 443 ssl;
server_name docker.benet.com;
ssl_certificate /etc/pki/CA/ssl/nginx.crt;
ssl_certificate_key /etc/pki/CA/ssl/nginx.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://registry;
client_max_body_size 3000m;
proxy_set_header Host $host;
proxy_set_header X-Forward-For $remote_addr;
}
}
}
相關(guān)選項含義:
ssl_session_cache會話緩存用于保存SSL會話,這些緩存在工作進程間共享,可以使用ssl_session_cache指令進行配置。1M緩存可以存放大約4000個會話。
ssl_session_timeout緩存超時,默認的緩存超時是5分鐘。
ssl_ciphers HIGH:!aNULL:!MD5使用高強度的加密算法
ssl_prefer_server_ciphers on依賴SSLv3和TLSv1協(xié)議的服務(wù)器密碼將優(yōu)先于客戶端密碼。即:在SSLv3或這是TLSv1握手時選擇一個密碼,通常是使用客戶端的偏好。如果這個指令是啟用的,那么服務(wù)器反而是使用服務(wù)器的偏好。
client_max_body_size即允許上傳文件大小的最大值
proxy_set_header Host $host和proxy_set_header X-Forward-For $remote_addr的作用描述:
nginx為了實現(xiàn)反向代理的需求而增加了一個ngx_http_proxy_module模塊。其中proxy_set_header指令就是該模塊需要讀取的配置文件。在這里,所有設(shè)置的值的含義和http請求同中的含義完全相同,除了Host外還有X-Forward-For。
Host的含義是表明請求的主機名,因為nginx作為反向代理使用,而如果后端真實的服務(wù)器設(shè)置有類似防盜鏈或者根據(jù)http請求頭中的host字段來進行路由或判斷功能的話,如果反向代理層的nginx不重寫請求頭中的host字段,將會導(dǎo)致請求失敗【默認反向代理服務(wù)器會向后端真實服務(wù)器發(fā)送請求,并且請求頭中的host字段應(yīng)為proxy_pass指令設(shè)置的服務(wù)器】。
同理,X_Forward_For字段表示該條http請求是有誰發(fā)起的?如果反向代理服務(wù)器不重寫該請求頭的話,那么后端真實服務(wù)器在處理時會認為所有的請求都來自反向代理服務(wù)器,如果后端有防攻擊策略的話,那么機器就被封掉了。因此,在配置用作反向代理的nginx中一般會增加兩條配置,修改http的請求頭:
proxy_set_header
Host $host;
proxy_set_header X-Forward-For $remote_addr;
這里的$host和$remote_addr都是nginx的導(dǎo)出變量,可以再配置文件中直接使用。
(5) 驗證配置
/opt/nginx/sbin/nginx -t
(6) 啟動nginx:
執(zhí)行/opt/nginx/sbin/nginx
(7) 驗證nginx是否啟動:
2、配置,運行Docker
(1) 停止docker服務(wù)
(2)編輯/etc/sysconfig/docker文件,加上如下一行
DOCKER_OPTS="--insecure-registry docker.benet.com --tlsverify --tlscacert /etc/pki/CA/cacert.pem"
(3) 把根證書復(fù)制到/etc/docker/certs.d/docker.yy.com/目錄下
mkdir -p /etc/docker/certs.d/docker.benet.com
cp /etc/pki/CA/cacert.pem /etc/docker/certs.d/docker.benet.com/ca-certificates.crt
(4) 啟動docker
3、運行私有倉庫容器
通過獲取官方 registry 鏡像來運行
docker search registry
docker pull registry
使用官方的 registry 鏡像來啟動本地的私有倉庫。用戶可以通過指定參數(shù)來配置私有倉庫位置。
例如將目錄/opt/data/registry作為私有倉庫的位置
運行私有倉庫容器
可以通過 -v 參數(shù)來將鏡像文件存放在本地的指定路徑。例如上面的例子將上傳的鏡像放到 /opt/data/registry 目錄。
-p(小寫的)用于將容器的5000端口映射宿主機的5000端口。
4)驗證registry:
用瀏覽器輸入: https://docker.benet.com
或者:curl -i -k https://docker.benet.com
curl是通過url語法在命令行下上傳或下載文件的工具軟件,它支持http,https,ftp,ftps,telnet等多種協(xié)議,常被用來抓取網(wǎng)頁和監(jiān)控Web服務(wù)器狀態(tài)
服務(wù)端的配置就到此完成!
注意:注意防火墻
5)Docker客戶端配置
(1)編輯/etc/hosts,把docker.benet.com的ip地址添加進來,例如:
(2)把docker registry服務(wù)器端的根證書追加到ca-certificates.crt文件里
先從docker registry服務(wù)器端把文件/etc/pki/CA/cacert.pem拷貝到本機,然后執(zhí)行命令:
cat ./cacert.pem>> /etc/pki/tls/certs/ca-certificates.crt
(3) 驗證docker.yy.com下的registry:
用瀏覽器輸入: https://docker.benet.com
或者:curl -i -k https://docker.benet.com
(4) 使用私有registry步驟:
登錄: docker login -u testuser -p pwd123 -e "test@benet.com" https://docker.benet.com
從Docker HUB 上拉取一個鏡像測試,為基礎(chǔ)鏡像打個標(biāo)簽:
docker tag centos:centos6 docker.benet.com/centos:centos6
發(fā)布:上傳鏡像到本地私有倉庫
docker push docker.benet.com/centos:centos6
查看私有倉庫是否有對應(yīng)的鏡像
# curl 192.168.0.167:5000/v1/search
查看鏡像的存儲目錄和文件(在鏡像服務(wù)器)
tree /opt/data/registry/repositories
從私有倉庫pull下來image,查看image
首先刪除所有鏡像
然后下載
查看私有倉庫是否有對應(yīng)的鏡像
或瀏覽器訪問倉庫
弊端:
server端可以login到官方的Docker Hub,可以pull,push官方和私有倉庫!
client端只能操作搭設(shè)好的私有倉庫!
私有倉庫不能search!
優(yōu)點:
所有的build,pull,push操作只能在私有倉庫的server端操作,降低企業(yè)風(fēng)險!
注意:當(dāng)client端docker login到官方的https://index.docker.io/v1/網(wǎng)站,出現(xiàn)x509: certificate signed by unknown authority錯誤時
重命名根證書mv /etc/pki/tls/certs/ca-certificates.crt /etc/pki/tls/certs/ca-certificates.crt.bak
重啟docker服務(wù)!systemctl restart docker
謝謝觀看,真心的希望能幫到您!
本文出自 “一盞燭光” 博客,謝絕轉(zhuǎn)載!
更多建議: