段子
今年基本已經結束了,我問了很多朋友今年掙錢了沒?大多朋友都有掙,而且掙得五花八門:有掙個屁的,有掙個錘子的,有掙個毛的,更有甚者掙個妹的,奢侈之極!最恐怖的是掙個鬼的!有的還可以,掙個球,下午我碰見一朋友,問今年掙了嗎?他望著天空喃喃自語:掙個鳥!看吧,只要肯努力,什么都能掙到。
年末將至,忽然發現,從創建開始到現在,整整一年時間,沒有寫過多少東西。為了留下一點痕跡,也是為了整理一下自己的收獲,為17年畫上一筆濃郁的色彩。
最近在看一本入門級機器學習的書,里面的案例基本上是python實現的,所以想搭建python相關的環境,然后又想偷懶,有一個運行環境,可以輕松安裝和編寫使用,也可以在其他地方使用,編寫工具首選jupyter notebook,當然,在大多數的書中也是比較推薦這個工具,自己之前也使用過,覺得不錯。還有個問題就是想在其他地方使用python環境和這個工具,不需要重復安裝,此刻,我想到的是docker。之前對docker只是簡單的理解,為此,特意學習了一下docker,現做分享。
上圖就是docker的圖標,這個圖標對docker的含義闡釋的還是比較全面:小鯨魚代表的是船,船上的就是集裝箱,所有的東西不管是什么,只要裝在集裝箱中,就可以方便的運輸。docker公司的口號是Build,Ship,and Run Any App,Anywhere。docker的本意是碼頭工人,而在這里說是集裝箱的話,比較貼切。所有需要運行的環境和程序,裝入docker,然后需要運行的時候,就運行這個特定的docker容器,提供特定的服務。
docker的通俗解析:點擊這里
剛開始的時候,搞不清楚docker和虛擬機有什么區別,總感覺docker能干的事虛擬機也能,并且在使用的時候,總按照虛擬機的操作思路去做。那docker為什么會出現?
我在docker的官方網站找到了兩張關于虛擬機和容器的區別:
容器 VS 虛擬機
容器和虛擬機具有相似的資源隔離和分配優勢,但功能有所不同,因為容器虛擬化的是操作系統,而不是硬件,因此容器更容易移植,效率也更高。
關于容器:點擊這里
對于docker做了簡單的了解之后,就需要實際去體驗一下安裝和構建容器,本例使用centos6.5:
1.安裝docker相關軟件
[root@bogon ubuntu-16.04]# rpm -ivh http://dl.Fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpmRetrieving http://dl.Fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpmwarning: /var/tmp/rpm-tmp.KYucBm: Header V3 RSA/SHA256 Signature, key ID 0608b895: NOKEYPreparing... ########################################### [100%] 1:epel-release ########################################### [100%][root@bogon ubuntu-16.04]# yum -y install docker-ioLoaded plugins: fastestmirror, refresh-packagekit, securityLoading mirror speeds from cached hostfile...Complete![root@bogon ubuntu-16.04]# service docker startStarting cgconfig service: [ OK ]Starting docker: [ OK ][root@bogon ubuntu-16.04]# chkconfig docker on[root@bogon ubuntu-16.04]#
使用service docker status查看docker服務狀態的時候,發現沒有啟動docker dead but pid file exists,執行docker相關命令(如docker ps)的時候會出現Cannot connect to the Docker daemon. Is 'docker -d' running on this host?,需要解決這個問題,如下:
[root@bogon ubuntu-16.04]# service docker statusdocker dead but pid file exists[root@bogon ubuntu-16.04]#yum-config-manager --enable public_ol6_latestLoaded plugins: fastestmirror, refresh-packagekit[root@bogon ubuntu-16.04]# yum install -y device-mapper-event-libsLoaded plugins: fastestmirror, refresh-packagekit, security...
2.構建基礎鏡像
在使用docker的時候后,可以通過命令docker pull <鏡像名稱>從鏡像庫中獲取,但是有時候會出現網絡問題或是其他原因,導致無法拉取,在docker中國官網介紹使用通過 Docker 官方鏡像加速來解決無法拉?。?/p>
您可以使用以下命令直接從該鏡像加速地址進行拉?。?/p>
$ docker pull registry.docker-cn.com/myname/myrepo:mytag
例如:
$ docker pull registry.docker-cn.com/library/ubuntu:16.04
原文如下:點擊這里
而在本文中,我使用Dockerfile來構建基礎鏡像ubuntu 16.04(xenial),其對應的Dockerfile的Github地址為:點擊這里,搜索方式為在hub.docker.com中搜索ubuntu,即可看見對應的鏡像信息。Dockerfile內容如下:
FROM scratchADD ubuntu-xenial-core-cloudimg-amd64-root.tar.gz /# a few minor docker-specific tweaks# see https://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrapRUN set -xe / /# https://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap#L40-L48 && echo '#!/bin/sh' > /usr/sbin/policy-rc.d / && echo 'exit 101' >> /usr/sbin/policy-rc.d / && chmod +x /usr/sbin/policy-rc.d / /# https://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap#L54-L56 && dpkg-divert --local --rename --add /sbin/initctl / && cp -a /usr/sbin/policy-rc.d /sbin/initctl / && sed -i 's/^exit.*/exit 0/' /sbin/initctl / /# https://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap#L71-L78 && echo 'force-unsafe-io' > /etc/dpkg/dpkg.cfg.d/docker-apt-speedup / /# https://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap#L85-L105 && echo 'DPkg::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; };' > /etc/apt/apt.conf.d/docker-clean / && echo 'APT::Update::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; };' >> /etc/apt/apt.conf.d/docker-clean / && echo 'Dir::Cache::pkgcache ""; Dir::Cache::srcpkgcache "";' >> /etc/apt/apt.conf.d/docker-clean / /# https://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap#L109-L115 && echo 'Acquire::Languages "none";' > /etc/apt/apt.conf.d/docker-no-languages / /# https://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap#L118-L130 && echo 'Acquire::GzipIndexes "true"; Acquire::CompressionTypes::Order:: "gz";' > /etc/apt/apt.conf.d/docker-gzip-indexes / /# https://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap#L134-L151 && echo 'Apt::AutoRemove::SuggestsImportant "false";' > /etc/apt/apt.conf.d/docker-autoremove-suggests# delete all the apt list files since they're big and get stale quicklyRUN rm -rf /var/lib/apt/lists/*# this forces "apt-get update" in dependent images, which is also good# enable the universeRUN sed -i 's/^#/s*/(deb.*universe/)$//1/g' /etc/apt/sources.list# make systemd-detect-virt return "docker"# See: https://github.com/systemd/systemd/blob/aa0c34279ee40bce2f9681b496922dedbadfca19/src/basic/virt.c#L434RUN mkdir -p /run/systemd && echo 'docker' > /run/systemd/container# overwrite this with 'CMD []' in a dependent DockerfileCMD ["/bin/bash"]
現在對Dockerfile中的相關命令解釋一下:
目前,這個Dockerfile中涉及的命令就這幾個,其他等以后遇到再進行說明。解釋完畢,開始構建:
[root@bogon ubuntu-16.04]# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES[root@bogon ubuntu-16.04]# docker imagesREPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE[root@bogon ubuntu-16.04]# pwd/home/ml/ubuntu-16.04[root@bogon ubuntu-16.04]# ll -htotal 40M-rw-rw-r--. 1 ml ml 2.8K Dec 19 12:37 Dockerfile-rw-rw-r--. 1 ml ml 40M Dec 19 12:39 ubuntu-xenial-core-cloudimg-amd64-root.tar.gz[root@bogon ubuntu-16.04]# [root@bogon ubuntu-16.04]# docker build -t ubuntu:16.04 .Sending build context to Docker daemon 41.94 MBSending build context to Docker daemon Step 0 : FROM scratch ---> Step 1 : ADD ubuntu-xenial-core-cloudimg-amd64-root.tar.gz / ---> 537c2f6dd023Removing intermediate container dee7679a7ee2Step 2 : RUN set -xe && echo '#!/bin/sh' > /usr/sbin/policy-rc.d && /echo 'exit 101' >> /usr/sbin/policy-rc.d && chmod +x /usr/sbin/policy-rc.d && /dpkg-divert --local --rename --add /sbin/initctl && cp -a /usr/sbin/policy-rc.d /sbin/initctl && sed -i 's/^exit.*/exit 0/' /sbin/initctl && / ...---> Running in 41d719b68981+ echo #!/bin/sh+ echo exit 101+ chmod +x /usr/sbin/policy-rc.d+ dpkg-divert --local --rename --add /sbin/initctlAdding 'local diversion of /sbin/initctl to /sbin/initctl.distrib'+ cp -a /usr/sbin/policy-rc.d /sbin/initctl+ sed -i s/^exit.*/exit 0/ /sbin/initctl+ echo force-unsafe-io+ echo DPkg::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; };+ echo APT::Update::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; };+ echo Dir::Cache::pkgcache ""; Dir::Cache::srcpkgcache "";+ echo Acquire::Languages "none";+ echo Acquire::GzipIndexes "true"; Acquire::CompressionTypes::Order:: "gz";+ echo Apt::AutoRemove::SuggestsImportant "false"; ---> c49bdbf61888Removing intermediate container 41d719b68981Step 3 : RUN rm -rf /var/lib/apt/lists/* ---> Running in 6389964016a2 ---> 4508181f7442Removing intermediate container 6389964016a2Step 4 : RUN sed -i 's/^#/s*/(deb.*universe/)$//1/g' /etc/apt/sources.list ---> Running in cbed2b28c988 ---> 8eed06df8f19Removing intermediate container cbed2b28c988Step 5 : RUN mkdir -p /run/systemd && echo 'docker' > /run/systemd/container ---> Running in aff40dbc6e05 ---> 19c96e7912a4Removing intermediate container aff40dbc6e05Step 6 : CMD /bin/bash ---> Running in 2469ee9d7251 ---> 77e565a65647Removing intermediate container 2469ee9d7251Successfully built 77e565a65647[root@bogon ubuntu-16.04]# docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZEubuntu 16.04 77e565a65647 33 seconds ago 110.5 MB[root@bogon ubuntu-16.04]#
從構建日志可以看出,每條命令為一個step,執行完成之后會產生一個id,類似于6389964016a2,其實,這就是鏡像的分層,一層層堆積在一起。
到此,一個ubuntu16.04版的docker鏡像構建完成,那么接下來就是運行
3.運行鏡像
使用docker run命令運行:
[root@bogon ubuntu-16.04]# docker run -it ubuntu:16.04root@5ea0b95e8641:/# cat /etc/issueUbuntu 16.04.3 LTS /n /lroot@5ea0b95e8641:/# ps -efUID PID PPID C STIME TTY TIME CMDroot 1 0 0 22:47 ? 00:00:00 /bin/bashroot 11 1 0 22:47 ? 00:00:00 ps -efroot@5ea0b95e8641:/#
其中5ea0b95e8641為當前容器的ID,進入容器查看所有進程,pid為1的時bash,linux不應該時init嗎?其實,這就是容器與虛擬機的差別,容器的init進程就是主機上docker服務進程,每個容器只是一個進程而已。其中的參數-it指的是前端打開并分配一個終端,-d為在后臺運行,我們試試當前這個可不可以使用-d:
[root@bogon ~]# docker run -d ubuntu:16.0443ae7ded8e6920b55b8e744b52ffce37b89b25182fcacdc10a5414e6621abff3[root@bogon ~]# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES[root@bogon ~]# docker run -d ubuntu:16.04 /bin/bash77f3ec2ebfb3f154772683eeea8ca7e2ba3b7756b1488f5f09818af424e0298e[root@bogon ~]# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
可以明顯的開出來,使用-d后,docker ps查不到任何運行的容器,如果使用-it的話,在別的shell下使用docker ps查看:
[root@bogon ml]# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES8341a332c788 ubuntu:16.04 "/bin/bash" 18 seconds ago Up 18 seconds drunk_cori
可以看到,有容器在運行,因為我們沒有退出。由此可以看出,容器其實以進程方式運行,執行完成/bin/bash之后,進程消亡,所以容器也就不存在,如果容器里面是一個tomcat服務,則是另外一種情況了。
基礎鏡像基本構建完成,后面的環境搭建,都將基于這個鏡像構建。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。
新聞熱點
疑難解答
圖片精選