docker技術(shù)剖析--dockerfile and registry(構(gòu)建容器和私有倉庫)

2018-06-08 18:08 更新

防偽碼:梅須遜雪三分白,雪卻輸梅一段香

                    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)載!

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號