防偽碼:梅須遜雪三分白,雪卻輸梅一段香
docker技術(shù)剖析--dockerfile and registry(構(gòu)建容器和私有倉(cāng)庫(kù))
一、根據(jù)Dockerfile構(gòu)建出一個(gè)容器
1、Dockfile是一種被Docker程序解釋的腳本,Dockerfile由一條一條的指令組成,每條指令對(duì)應(yīng)Linux下面的一條命令。Docker程序?qū)⑦@些Dockerfile指令翻譯真正的Linux命令。Dockerfile有自己書(shū)寫(xiě)格式和支持的命令,Docker程序解決這些命令間的依賴關(guān)系,類似于Makefile。2、Docker程序?qū)⒆x取Dockerfile,根據(jù)指令生成定制的image。相比image這種黑盒子,Dockerfile這種顯而易見(jiàn)的腳本更容易被使用者接受,它明確的表明image是怎么產(chǎn)生的。有了Dockerfile,當(dāng)我們需要定制自己額外的需求時(shí),只需在Dockerfile上添加或者修改指令,重新生成image即可,省去了敲命令的麻煩。
3、Dockerfile由一行行命令語(yǔ)句組成,并且支持以 # 開(kāi)頭的注釋行。
4、Dockerfile的指令是忽略大小寫(xiě)的,建議使用大寫(xiě),每一行只支持一條指令,每條指令可以攜帶多個(gè)參數(shù)。
5、Dockerfile的指令根據(jù)作用可以分為兩種,構(gòu)建指令和設(shè)置指令。構(gòu)建指令用于構(gòu)建image,其指定的操作不會(huì)在運(yùn)行image的容器上執(zhí)行;設(shè)置指令用于設(shè)置image的屬性,其指定的操作將在運(yùn)行image的容器中執(zhí)行。
一般的,Dockerfile分為四部分:基礎(chǔ)鏡像信息、維護(hù)者信息、鏡像操作指令和容器啟動(dòng)時(shí)執(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
其中,一開(kāi)始必須指明所基于的鏡像名稱,接下來(lái)推薦說(shuō)明維護(hù)者信息。
后面則是鏡像操作指令,例如 RUN 指令, RUN 指令將對(duì)鏡像執(zhí)行跟隨的命令。每運(yùn)行一條 RUN 指令,鏡像添加新的一層,并提交。
最后是 CMD 指令,來(lái)指定運(yùn)行容器時(shí)的操作命令。
dockerfile指令
指令的一般格式為 INSTRUCTION arguments ,指令包括 FROM 、 MAINTAINER 、 RUN 等。
(1)FROM(指定基礎(chǔ)image)
構(gòu)建指令,必須指定且需要在Dockerfile其他指令的前面。后續(xù)的指令都依賴于該指令指定的image。FROM指令指定的基礎(chǔ)image可以是官方遠(yuǎn)程倉(cāng)庫(kù)中的,也可以位于本地倉(cāng)庫(kù)。
該指令有兩種格式:
FROM <image>
指定基礎(chǔ)image為該image的最后修改的版本。
或者:
FROM <image>:<tag>
指定基礎(chǔ)image為該image的一個(gè)tag版本。
(2)MAINTAINER(用來(lái)指定鏡像創(chuàng)建者信息)
構(gòu)建指令,用于將image的制作者相關(guān)的信息寫(xiě)入到image中。當(dāng)我們對(duì)該image執(zhí)行docker
inspect命令時(shí),輸出中有相應(yīng)的字段記錄該信息。
格式:
MAINTAINER <name>
(3)RUN(安裝軟件用)
構(gòu)建指令,RUN可以運(yùn)行任何被基礎(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 終端中運(yùn)行命令,即 /bin/sh -c ;后者則使用 exec 執(zhí)行。
指定使用其它終端可以通過(guò)第二種方式實(shí)現(xiàn),例如 RUN ["/bin/bash", "-c", "echo hello"] 。
每條 RUN 指令將在當(dāng)前鏡像基礎(chǔ)上執(zhí)行指定命令,并提交為新的鏡像。當(dāng)命令較長(zhǎng)時(shí)可以使用 \ 來(lái)?yè)Q行。
(4)CMD(設(shè)置container啟動(dòng)時(shí)執(zhí)行的操作)
該指令有三種格式:
設(shè)置指令,用于container啟動(dòng)時(shí)指定的操作。該操作可以是執(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 的默認(rèn)參數(shù);
ENTRYPOINT指定的是一個(gè)可執(zhí)行的腳本或者程序的路徑,該指定的腳本或者程序?qū)?huì)以param1和param2作為參數(shù)執(zhí)行。所以如果CMD指令使用上面的形式,那么Dockerfile中必須要有配套的ENTRYPOINT。
指定啟動(dòng)容器時(shí)執(zhí)行的命令,每個(gè)Dockerfile只能有一條 CMD 命令。如果指定了多條命令,只有最后一條會(huì)被執(zhí)行。
如果用戶啟動(dòng)容器時(shí)候指定了運(yùn)行的命令,則會(huì)覆蓋掉 CMD 指定的命令。
(5)ENTRYPOINT(設(shè)置container啟動(dòng)時(shí)執(zhí)行的操作)
設(shè)置指令,指定容器啟動(dòng)時(shí)執(zhí)行的命令,可以多次設(shè)置,但是只有最后一個(gè)有效。
兩種格式:
ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2 (shell中執(zhí)行)。
配置容器啟動(dòng)后執(zhí)行的命令,并且不可被 docker run 提供的參數(shù)覆蓋。
每個(gè) Dockerfile 中只能有一個(gè) ENTRYPOINT ,當(dāng)指定多個(gè)時(shí),只有最后一個(gè)起效。
該指令的使用分為兩種情況,一種是獨(dú)自使用,另一種和CMD指令配合使用。
當(dāng)獨(dú)自使用時(shí),如果你還使用了CMD命令且CMD是一個(gè)完整的可執(zhí)行的命令,那么CMD指令和ENTRYPOINT會(huì)互相覆蓋只有最后一個(gè)CMD或者ENTRYPOINT有效。
例如:CMD指令將不會(huì)被執(zhí)行,只有ENTRYPOINT指令被執(zhí)行
CMD echo “Hello, World!”
ENTRYPOINT ls -l
另一種用法和CMD指令配合使用來(lái)指定ENTRYPOINT的默認(rèn)參數(shù),這時(shí)CMD指令不是一個(gè)完整的可執(zhí)行命令,僅僅是參數(shù)部分;ENTRYPOINT指令只能使用JSON方式指定執(zhí)行命令,而不能指定參數(shù)。
例如
FROM ubuntu
CMD ["-l"]
ENTRYPOINT ["/usr/bin/ls"]
(6)USER(設(shè)置container容器的用戶,默認(rèn)是root用戶)
格式為 USER daemon
指定運(yùn)行容器時(shí)的用戶名或 UID,后續(xù)的 RUN 也會(huì)使用指定用戶。
當(dāng)服務(wù)不需要管理員權(quán)限時(shí),可以通過(guò)該命令指定運(yùn)行用戶。并且可以在之前創(chuàng)建所需要的用戶,例
如: RUN groupadd -r postgres&&useradd -r -g postgrespostgres
例如: 指定memcached的運(yùn)行用戶
ENTRYPOINT ["memcached"]
USER daemon
或
ENTRYPOINT ["memcached", "-u", "daemon"]
(7)EXPOSE(指定容器需要映射到宿主機(jī)器的端口)
格式為 EXPOSE <port> [<port>...]
設(shè)置指令,該指令會(huì)將容器中的端口映射成宿主機(jī)器中的某個(gè)端口。當(dāng)你需要訪問(wèn)容器的時(shí)候,可以不是用容器的IP地址而是使用宿主機(jī)器的IP地址和映射后的端口。
要完成整個(gè)操作需要兩個(gè)步驟,首先在Dockerfile使用EXPOSE設(shè)置需要映射的容器端口,然后在運(yùn)行容器的時(shí)候指定-p選項(xiàng)加上EXPOSE設(shè)置的端口,這樣EXPOSE設(shè)置的端口號(hào)會(huì)被隨機(jī)映射成宿主機(jī)器中的一個(gè)端口號(hào)。也可以指定需要映射到宿主機(jī)器的那個(gè)端口,這時(shí)要確保宿主機(jī)器上的端口號(hào)沒(méi)有被使用。EXPOSE指令可以一次設(shè)置多個(gè)端口號(hào),相應(yīng)的運(yùn)行容器的時(shí)候,可以配套的多次使用-p選項(xiàng)。
例如: 映射一個(gè)端口
EXPOSE port1
# 相應(yīng)的運(yùn)行容器使用的命令
docker run -p port1 image
例如: 映射多個(gè)端口
EXPOSE port1 port2 port3
# 相應(yīng)的運(yùn)行容器使用的命令
docker run -p port1 -p port2 -p port3 image
# 還可以指定需要映射到宿主機(jī)器上的某個(gè)端口號(hào)
docker run -p host_port1:port1 -p host_port2:port2 -p host_port3:port3 image
端口映射是docker比較重要的一個(gè)功能,原因在于我們每次運(yùn)行容器的時(shí)候容器的IP地址不能指定而是在橋接網(wǎng)卡的地址范圍內(nèi)隨機(jī)生成的。宿主機(jī)器的IP地址是固定的,我們可以將容器的端口的映射到宿主機(jī)器上的一個(gè)端口,免去每次訪問(wèn)容器中的某個(gè)服務(wù)時(shí)都要查看容器的IP的地址。
對(duì)于一個(gè)運(yùn)行的容器,可以使用docker port加上容器中需要映射的端口和容器的ID來(lái)查看該端口號(hào)在宿主機(jī)器上的映射端口
(8)ENV(用于設(shè)置環(huán)境變量)
構(gòu)建指令,指定一個(gè)環(huán)境變量,會(huì)被后續(xù) RUN 指令使用,并在容器運(yùn)行時(shí)保持。
格式:
ENV <key> <value>
設(shè)置了后,后續(xù)的RUN命令都可以使用,container啟動(dòng)后,可以通過(guò)docker
inspect查看這個(gè)環(huán)境變量,也可以通過(guò)在docker run --env key=value時(shí)設(shè)置或修改環(huán)境變量。
假如你安裝了JAVA程序,需要設(shè)置JAVA_HOME,那么可以在Dockerfile中這樣寫(xiě):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;
如果是一個(gè)目錄,那么會(huì)將該目錄下的所有文件添加到container中,不包括目錄;
如果文件是可識(shí)別的壓縮格式,則docker會(huì)幫忙解壓縮(注意壓縮格式);
如果<src>是文件且<dest>中不使用斜杠結(jié)束,則會(huì)將<dest>視為文件,<src>的內(nèi)容會(huì)寫(xiě)入<dest>;
如果<src>是文件且<dest>中使用斜杠結(jié)束,則會(huì)<src>文件拷貝到<dest>目錄下。
格式:
ADD <src> <dest>
該命令將復(fù)制指定的<src>到容器中的<dest>。
其中<src>可以是Dockerfile所在目錄的一個(gè)相對(duì)路徑;也可以是一個(gè) URL;還可以是一個(gè) tar 文件(自動(dòng)解壓為目錄)
<dest>是container中的絕對(duì)路徑(10)COPY
格式為 COPY <src><dest>
復(fù)制本地主機(jī)的<src>(為Dockerfile所在目錄的相對(duì)路徑)到容器中的<dest>。
(11)VOLUME(指定掛載點(diǎn))
設(shè)置指令,使容器中的一個(gè)目錄具有持久化存儲(chǔ)數(shù)據(jù)的功能,該目錄可以被容器本身使用,也可以共享給其他容器使用。我們知道容器使用的是AUFS,這種文件系統(tǒng)不能持久化數(shù)據(jù),當(dāng)容器關(guān)閉后,所有的更改都會(huì)丟失。當(dāng)容器中的應(yīng)用有持久化數(shù)據(jù)的需求時(shí)可以在Dockerfile中使用該指令。
格式:
VOLUME ["<mountpoint>"]
例如:FROM base
VOLUME ["/tmp/data"]
運(yùn)行通過(guò)該Dockerfile生成image的容器,/tmp/data目錄中的數(shù)據(jù)在容器關(guān)閉后,里面的數(shù)據(jù)還存在。例如另一個(gè)容器也有持久化數(shù)據(jù)的需求,且想使用上面容器共享的/tmp/data目錄,那么可以運(yùn)行下面的命令啟動(dòng)一個(gè)容器:
docker run -t -i -rm -volumes-from container1 image2 bash
container1為第一個(gè)容器的ID,image2為第二個(gè)容器運(yùn)行image的名字。
(12)WORKDIR(切換目錄)
設(shè)置指令,可以多次切換(相當(dāng)于cd命令),對(duì)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
可以使用多個(gè) WORKDIR 指令,后續(xù)命令如果參數(shù)是相對(duì)路徑,則會(huì)基于之前命令指定的路徑。
例如
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
則最終路徑為 /a/b/c 。
(13)ONBUILD(在子鏡像中執(zhí)行)
ONBUILD <Dockerfile關(guān)鍵字>
ONBUILD 指定的命令在構(gòu)建鏡像時(shí)并不執(zhí)行,而是在它的子鏡像中執(zhí)行。
格式為 ONBUILD [INSTRUCTION] 。
配置當(dāng)所創(chuàng)建的鏡像作為其它新創(chuàng)建鏡像的基礎(chǔ)鏡像時(shí),所執(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)建新的鏡像時(shí),新的Dockerfile中使用 FROM image-A 指定基礎(chǔ)鏡像時(shí),會(huì)自動(dòng)執(zhí)行ONBUILD 指令內(nèi)容。
等價(jià)于在后面添加了兩條指令。
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 。
編寫(xiě)完成Dockerfile之后,可以通過(guò)docker build 命令來(lái)創(chuàng)建鏡像。
基本的格式為docker build [選項(xiàng)] 路徑,該命令將讀取指定路徑下的Dockerfile,并將該路徑下所有內(nèi)容發(fā)送給 Docker 服務(wù)端,由服務(wù)端來(lái)創(chuàng)建鏡像。因此一般建議放置Dockerfile的目錄為空目錄。
要指定鏡像的標(biāo)簽信息,可以通過(guò) -t 選項(xiàng),例如
$ sudodocker build –tmyrepo/myapp/tmp/test1/
1) 創(chuàng)建一個(gè)sshd_dockerfile工作目錄
編輯run.sh文件
在主機(jī)上生成ssh秘鑰對(duì),并創(chuàng)建authorized_keys文件
2) 編寫(xiě)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"]
以上選項(xiàng)的含義解釋:
FROM centos:centos6選擇一個(gè)已有的os鏡像作為基礎(chǔ)
MAINTAINER 鏡像的作者
RUN yum install -y openssh-server sudo安裝openssh-server和sudo軟件包
添加測(cè)試用戶admin,密碼admin,并且將此用戶添加到sudoers里
RUN useradd admin
RUN echo "admin:admin" | chpasswd
RUN echo "admin ALL=(ALL) ALL" >> /etc/sudoers
下面這兩句比較特殊,在centos6上必須要有,否則創(chuàng)建出來(lái)的容器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)建出來(lái)的容器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
將公鑰信息上傳到遠(yuǎn)程連接用戶的宿主目錄的.ssh下
ADD authorized_keys /home/admin/.ssh/authorized_keys
啟動(dòng)sshd服務(wù)并且暴露22端口
RUN mkdir /var/run/sshd
EXPOSE 22 80
CMD ["/run.sh"] 也可以寫(xiě)成這種方式CMD ["/usr/sbin/sshd", "-D"]
在sshd_dockerfile目錄下,使用docker build命令來(lái)創(chuàng)建鏡像,注意:在最后還有一個(gè)”.”,表示使用當(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
使用剛才建好的鏡像運(yùn)行一個(gè)容器,將容器的端口映射到主機(jī)的10122
[root@localhost ~]# docker run -dit --name webserver1 -p 10122:22 -p 80:80 --restart=always centos:httpdv1
[root@localhost ~]# docker ps
在宿主主機(jī)打開(kāi)一個(gè)終端,連接剛才新建的容器
注:admin用戶是容器中的用戶,192.168.152.142是宿主機(jī)的地址。
測(cè)試sudo執(zhí)行授權(quán)命令:
或
用docker inspect查看容器的ip地址,在宿主機(jī)上直接ssh連接容器
二、Docker倉(cāng)庫(kù)
倉(cāng)庫(kù)(Repository)是集中存放鏡像的地方。
一個(gè)容易混淆的概念是注冊(cè)服務(wù)器(Registry)。實(shí)際上注冊(cè)服務(wù)器是管理倉(cāng)庫(kù)的具體服務(wù)器,每個(gè)服務(wù)器上可以有多個(gè)倉(cāng)庫(kù),而每個(gè)倉(cāng)庫(kù)下面有多個(gè)鏡像。從這方面來(lái)說(shuō),倉(cāng)庫(kù)可以被認(rèn)為是一個(gè)具體的項(xiàng)目或目錄。例如對(duì)于倉(cāng)庫(kù)地址 docker.sina.com.cn/centos:centos63 來(lái)說(shuō),docker.sina.com.cn 是注冊(cè)服務(wù)器地址,centos 是倉(cāng)庫(kù)名,centos6是倉(cāng)庫(kù)的 tag。
Docker Hub 官方倉(cāng)庫(kù)
目前 Docker 官方維護(hù)了一個(gè)公共倉(cāng)庫(kù) Docker Hub,其中已經(jīng)包括了超過(guò) 15,000 的鏡像。大部分需求,都可以通過(guò)在 Docker Hub 中直接下載鏡像來(lái)實(shí)現(xiàn)。
注冊(cè)&登錄
可以通過(guò)命令行執(zhí)行docker login 命令來(lái)輸入用戶名、密碼和郵箱來(lái)完成注冊(cè)和登錄。注冊(cè)成功后,本地用戶目錄的 .docker/config.json中將保存用戶的認(rèn)證信息。
基本操作
用戶無(wú)需登錄即可通過(guò)docker search 命令來(lái)查找官方倉(cāng)庫(kù)中的鏡像,并利用docker pull 命令來(lái)將它下載到本地。
例如以 centos 為關(guān)鍵詞進(jìn)行搜索:
可以看到返回了很多包含關(guān)鍵字的鏡像,其中包括鏡像名字、描述、星級(jí)(表示該鏡像的受歡迎程度)、是否官方創(chuàng)建、是否自動(dòng)創(chuàng)建。官方的鏡像說(shuō)明是官方項(xiàng)目組創(chuàng)建和維護(hù)的,automated 資源允許用戶驗(yàn)證鏡像的來(lái)源和內(nèi)容。
根據(jù)是否是官方提供,可將鏡像資源分為兩類。一種是類似 centos 這樣的基礎(chǔ)鏡像,被稱為基礎(chǔ)或根鏡像。這些基礎(chǔ)鏡像是由 Docker 公司創(chuàng)建、驗(yàn)證、支持、提供。這樣的鏡像往往使用單個(gè)單詞作為名字。還有一種類型,比如tianon/centos 鏡像,它是由 Docker 的用戶創(chuàng)建并維護(hù)的,往往帶有用戶名稱前綴??梢酝ㄟ^(guò)前綴user_name/ 來(lái)指定使用某個(gè)用戶提供的鏡像,比如tianon用戶。另外,在查找的時(shí)候通過(guò) -s N 參數(shù)可以指定僅顯示評(píng)價(jià)為 N 星以上的鏡像。
創(chuàng)建自己的倉(cāng)庫(kù)----鏡像倉(cāng)庫(kù)
拓?fù)洌?/span>
說(shuō)明:
docker.benet.com 這是docker registry服務(wù)器的主機(jī)名稱,ip是192.168.1.107;因?yàn)閔ttps的SSL證書(shū)要用到主機(jī)名,所以要設(shè)置主機(jī)名。
dockerregistry 服務(wù)器作為處理docker鏡像的最終上傳和下載,用的是官方的鏡像registry。
nginx 1.6.x 是一個(gè)用nginx作為反向代理服務(wù)器
注:關(guān)閉selinux
1)私有倉(cāng)庫(kù)https支持:
A)安裝依賴軟件包:
在Nginx編譯需要PCRE,因?yàn)镹ginx的Rewrite模塊和HTTP核心模塊會(huì)使用到PCRE正則表達(dá)式。需要安裝pcre和pcre-devel用yum就能安裝。
Zlib庫(kù)提供了開(kāi)發(fā)人員的壓縮算法,在nginx的模塊中需要使用gzip壓縮。
需要安裝zlib和zlib-devel用yum就可以安裝
在Nginx中如果需要為服務(wù)器提供安全則需要用到OpenSSL庫(kù)。
需要安裝的是openssl和openssl-devel。用yum就可以安裝。
B)配置SSL
(1) 編輯/etc/hosts,把docker.benet.com的ip地址添加進(jìn)來(lái),例如:
主機(jī)名、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) 生成根證書(shū)
執(zhí)行
輸出如下信息
會(huì)提示輸入一些內(nèi)容,因?yàn)槭撬接械模钥梢噪S便輸入,最好記住能與后面保持一致,特別是"Common Name”。必須要和hostname顯示的一致。
上面的自簽證書(shū)cacert.pem應(yīng)該生成在/etc/pki/CA下。
(4) 為nginx web服務(wù)器生成ssl密鑰
注:因?yàn)镃A中心與要申請(qǐng)證書(shū)的nginx服務(wù)器是同一個(gè)所以就在本機(jī)上執(zhí)行為nginx服務(wù)器生成ssl密鑰了,否則應(yīng)該是在另一臺(tái)需要用到證書(shū)的服務(wù)器上生成。
查看nginx服務(wù)器的密鑰
(5) 為nginx生成證書(shū)簽署請(qǐng)求
執(zhí)行
openssl req -new -key nginx.key -out nginx.csr
輸出如下信息
同樣會(huì)提示輸入一些內(nèi)容,Commone Name一定要是你要授予證書(shū)的服務(wù)器域名或主機(jī)名,challenge password不填。
(6) 私有CA根據(jù)請(qǐng)求來(lái)簽發(fā)證書(shū)
執(zhí)行
openssl ca -in nginx.csr -out nginx.crt
輸出內(nèi)容:
同樣會(huì)提示輸入一些內(nèi)容,選擇y就可以了!
查看nginx的證書(shū)
C)安裝,配置,運(yùn)行nginx
(1) 添加組和用戶
(2) 下載nginx源文件:
wget http://nginx.org/download/nginx-1.11.2.tar.gz
(3) 編譯,安裝nginx:
上述選項(xiàng)的解釋:
--user=USER 設(shè)定程序運(yùn)行的用戶環(huán)境(www)
--group=GROUP 設(shè)定程序運(yùn)行的組環(huán)境(www)
--prefix=PATH 設(shè)定安裝目錄
--with-pcre啟用pcre庫(kù),Nginx的Rewrite模塊和HTTP核心模塊會(huì)使用到PCRE正則表達(dá)式
--with-http_stub_status_module 是為了啟用 nginx 的 NginxStatus 功能,用來(lái)監(jiān)控 Nginx 的當(dāng)前狀態(tài)
--with-http_ssl_module 開(kāi)啟SSL模塊,支持使用HTTPS協(xié)議的網(wǎng)頁(yè)
--with-http_realip_module 開(kāi)啟Real IP的支持,該模塊用于從客戶請(qǐng)求的頭數(shù)據(jù)中讀取Real Ip地址
--with-http_addition_module 開(kāi)啟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)選項(xiàng)含義:
ssl_session_cache會(huì)話緩存用于保存SSL會(huì)話,這些緩存在工作進(jìn)程間共享,可以使用ssl_session_cache指令進(jìn)行配置。1M緩存可以存放大約4000個(gè)會(huì)話。
ssl_session_timeout緩存超時(shí),默認(rèn)的緩存超時(shí)是5分鐘。
ssl_ciphers HIGH:!aNULL:!MD5使用高強(qiáng)度的加密算法
ssl_prefer_server_ciphers on依賴SSLv3和TLSv1協(xié)議的服務(wù)器密碼將優(yōu)先于客戶端密碼。即:在SSLv3或這是TLSv1握手時(shí)選擇一個(gè)密碼,通常是使用客戶端的偏好。如果這個(gè)指令是啟用的,那么服務(wù)器反而是使用服務(wù)器的偏好。
client_max_body_size即允許上傳文件大小的最大值
proxy_set_header Host $host和proxy_set_header X-Forward-For $remote_addr的作用描述:
nginx為了實(shí)現(xiàn)反向代理的需求而增加了一個(gè)ngx_http_proxy_module模塊。其中proxy_set_header指令就是該模塊需要讀取的配置文件。在這里,所有設(shè)置的值的含義和http請(qǐng)求同中的含義完全相同,除了Host外還有X-Forward-For。
Host的含義是表明請(qǐng)求的主機(jī)名,因?yàn)閚ginx作為反向代理使用,而如果后端真實(shí)的服務(wù)器設(shè)置有類似防盜鏈或者根據(jù)http請(qǐng)求頭中的host字段來(lái)進(jìn)行路由或判斷功能的話,如果反向代理層的nginx不重寫(xiě)請(qǐng)求頭中的host字段,將會(huì)導(dǎo)致請(qǐng)求失敗【默認(rèn)反向代理服務(wù)器會(huì)向后端真實(shí)服務(wù)器發(fā)送請(qǐng)求,并且請(qǐng)求頭中的host字段應(yīng)為proxy_pass指令設(shè)置的服務(wù)器】。
同理,X_Forward_For字段表示該條http請(qǐng)求是有誰(shuí)發(fā)起的?如果反向代理服務(wù)器不重寫(xiě)該請(qǐng)求頭的話,那么后端真實(shí)服務(wù)器在處理時(shí)會(huì)認(rèn)為所有的請(qǐng)求都來(lái)自反向代理服務(wù)器,如果后端有防攻擊策略的話,那么機(jī)器就被封掉了。因此,在配置用作反向代理的nginx中一般會(huì)增加兩條配置,修改http的請(qǐng)求頭:
proxy_set_header
Host $host;
proxy_set_header X-Forward-For $remote_addr;
這里的$host和$remote_addr都是nginx的導(dǎo)出變量,可以再配置文件中直接使用。
(5) 驗(yàn)證配置
/opt/nginx/sbin/nginx -t
(6) 啟動(dòng)nginx:
執(zhí)行/opt/nginx/sbin/nginx
(7) 驗(yàn)證nginx是否啟動(dòng):
2、配置,運(yùn)行Docker
(1) 停止docker服務(wù)
(2)編輯/etc/sysconfig/docker文件,加上如下一行
DOCKER_OPTS="--insecure-registry docker.benet.com --tlsverify --tlscacert /etc/pki/CA/cacert.pem"
(3) 把根證書(shū)復(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) 啟動(dòng)docker
3、運(yùn)行私有倉(cāng)庫(kù)容器
通過(guò)獲取官方 registry 鏡像來(lái)運(yùn)行
docker search registry
docker pull registry
使用官方的 registry 鏡像來(lái)啟動(dòng)本地的私有倉(cāng)庫(kù)。用戶可以通過(guò)指定參數(shù)來(lái)配置私有倉(cāng)庫(kù)位置。
例如將目錄/opt/data/registry作為私有倉(cāng)庫(kù)的位置
運(yùn)行私有倉(cāng)庫(kù)容器
可以通過(guò) -v 參數(shù)來(lái)將鏡像文件存放在本地的指定路徑。例如上面的例子將上傳的鏡像放到 /opt/data/registry 目錄。
-p(小寫(xiě)的)用于將容器的5000端口映射宿主機(jī)的5000端口。
4)驗(yàn)證registry:
用瀏覽器輸入: https://docker.benet.com
或者:curl -i -k https://docker.benet.com
curl是通過(guò)url語(yǔ)法在命令行下上傳或下載文件的工具軟件,它支持http,https,ftp,ftps,telnet等多種協(xié)議,常被用來(lái)抓取網(wǎng)頁(yè)和監(jiān)控Web服務(wù)器狀態(tài)
服務(wù)端的配置就到此完成!
注意:注意防火墻
5)Docker客戶端配置
(1)編輯/etc/hosts,把docker.benet.com的ip地址添加進(jìn)來(lái),例如:
(2)把docker registry服務(wù)器端的根證書(shū)追加到ca-certificates.crt文件里
先從docker registry服務(wù)器端把文件/etc/pki/CA/cacert.pem拷貝到本機(jī),然后執(zhí)行命令:
cat ./cacert.pem>> /etc/pki/tls/certs/ca-certificates.crt
(3) 驗(yàn)證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 上拉取一個(gè)鏡像測(cè)試,為基礎(chǔ)鏡像打個(gè)標(biāo)簽:
docker tag centos:centos6 docker.benet.com/centos:centos6
發(fā)布:上傳鏡像到本地私有倉(cāng)庫(kù)
docker push docker.benet.com/centos:centos6
查看私有倉(cāng)庫(kù)是否有對(duì)應(yīng)的鏡像
# curl 192.168.0.167:5000/v1/search
查看鏡像的存儲(chǔ)目錄和文件(在鏡像服務(wù)器)
tree /opt/data/registry/repositories
從私有倉(cāng)庫(kù)pull下來(lái)image,查看image
首先刪除所有鏡像
然后下載
查看私有倉(cāng)庫(kù)是否有對(duì)應(yīng)的鏡像
或瀏覽器訪問(wèn)倉(cāng)庫(kù)
弊端:
server端可以login到官方的Docker Hub,可以pull,push官方和私有倉(cāng)庫(kù)!
client端只能操作搭設(shè)好的私有倉(cāng)庫(kù)!
私有倉(cāng)庫(kù)不能search!
優(yōu)點(diǎn):
所有的build,pull,push操作只能在私有倉(cāng)庫(kù)的server端操作,降低企業(yè)風(fēng)險(xiǎn)!
注意:當(dāng)client端docker login到官方的https://index.docker.io/v1/網(wǎng)站,出現(xiàn)x509: certificate signed by unknown authority錯(cuò)誤時(shí)
重命名根證書(shū)mv /etc/pki/tls/certs/ca-certificates.crt /etc/pki/tls/certs/ca-certificates.crt.bak
重啟docker服務(wù)!systemctl restart docker
謝謝觀看,真心的希望能幫到您!
本文出自 “一盞燭光” 博客,謝絕轉(zhuǎn)載!
更多建議: