從零開始構建docker基礎鏡像

 段子前端

  今年基本已經結束了,我問了不少朋友今年掙錢了沒?大多朋友都有掙,並且掙得五花八門:有掙個屁的,有掙個錘子的,有掙個毛的,更有甚者掙個妹的,奢侈之極!最恐怖的是掙個鬼的!有的還能夠,掙個球,下午我遇見一朋友,問今年掙了嗎?他望着天空喃喃自語:掙個鳥!看吧,只要肯努力,什麼都能掙到。python

 

  年底將至,突然發現,從建立開始到如今,整整一年時間,沒有寫過多少東西。爲了留下一點痕跡,也是爲了整理一下本身的收穫,爲17年畫上一筆濃郁的色彩。linux

  最近在看一本入門級機器學習的書,裏面的案例基本上是python實現的,因此想搭建python相關的環境,而後又想偷懶,有一個運行環境,能夠輕鬆安裝和編寫使用,也能夠在其餘地方使用,編寫工具首選jupyter notebook,固然,在大多數的書中也是比較推薦這個工具,本身以前也使用過,以爲不錯。還有個問題就是想在其餘地方使用python環境和這個工具,不須要重複安裝,此刻,我想到的是docker。以前對docker只是簡單的理解,爲此,特地學習了一下docker,現作分享。git

  上圖就是docker的圖標,這個圖標對docker的含義闡釋的仍是比較全面:小鯨魚表明的是船,船上的就是集裝箱,全部的東西不論是什麼,只要裝在集裝箱中,就能夠方便的運輸。docker公司的口號是Build,Ship,and Run Any App,Anywhere。docker的本意是碼頭工人,而在這裏說是集裝箱的話,比較貼切。全部須要運行的環境和程序,裝入docker,而後須要運行的時候,就運行這個特定的docker容器,提供特定的服務。github

  docker的通俗解析:點擊這裏docker

  剛開始的時候,搞不清楚docker和虛擬機有什麼區別,總感受docker能幹的事虛擬機也能,而且在使用的時候,總按照虛擬機的操做思路去作。那docker爲何會出現?shell

  我在docker的官方網站找到了兩張關於虛擬機和容器的區別:bootstrap

容器 VS 虛擬機

VM        

COntainer

  容器和虛擬機具備類似的資源隔離和分配優點,但功能有所不一樣,由於容器虛擬化的是操做系統,而不是硬件,所以容器更容易移植,效率也更高。ubuntu

  關於容器:點擊這裏c#

  

  對於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.rpm
Retrieving http://dl.Fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
warning: /var/tmp/rpm-tmp.KYucBm: Header V3 RSA/SHA256 Signature, key ID 0608b895: NOKEY Preparing... ########################################### [100%] 1:epel-release           ########################################### [100%] [root@bogon ubuntu-16.04]# yum -y install docker-io Loaded plugins: fastestmirror, refresh-packagekit, security Loading mirror speeds from cached hostfile ... Complete! [root@bogon ubuntu-16.04]# service docker start Starting 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 status docker dead but pid file exists [root@bogon ubuntu-16.04]#yum-config-manager --enable public_ol6_latest Loaded plugins: fastestmirror, refresh-packagekit [root@bogon ubuntu-16.04]# yum install -y device-mapper-event-libs Loaded plugins: fastestmirror, refresh-packagekit, security ...

2.構建基礎鏡像

  在使用docker的時候後,能夠經過命令docker pull <鏡像名稱>從鏡像庫中獲取,可是有時候會出現網絡問題或是其餘緣由,致使沒法拉取,在docker中國官網介紹使用經過 Docker 官方鏡像加速來解決沒法拉取:

您可使用如下命令直接從該鏡像加速地址進行拉取:

$ 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 scratch
ADD ubuntu-xenial-core-cloudimg-amd64-root.tar.gz /

# a few minor docker-specific tweaks
# see https://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap
RUN 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 quickly
RUN rm -rf /var/lib/apt/lists/*
# this forces "apt-get update" in dependent images, which is also good

# enable the universe
RUN 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#L434
RUN mkdir -p /run/systemd && echo 'docker' > /run/systemd/container

# overwrite this with 'CMD []' in a dependent Dockerfile
CMD ["/bin/bash"]

  如今對Dockerfile中的相關命令解釋一下:

    • FROM 指的是依賴的基礎鏡像,如scratch表示的是空白的,從零開始的。依賴的鏡像能夠是本地的,也能夠是遠程庫的
    • ADD 指的是添加本地文件到鏡像中,若是遇到linux可解壓格式文件,會自動解壓,這就是爲何整個文件中沒有對tar.gz進行顯式解壓
    • RUN 運行命令,如安裝軟件的相關命令
    • CMD 設置啓動Container時默認執行的命令,這個能夠在啓動容器時覆蓋

  目前,這個Dockerfile中涉及的命令就這幾個,其餘等之後遇到再進行說明。解釋完畢,開始構建:

[root@bogon ubuntu-16.04]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES [root@bogon ubuntu-16.04]# docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE [root@bogon ubuntu-16.04]# pwd
/home/ml/ubuntu-16.04 [root@bogon ubuntu-16.04]# ll -h total 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 MB Sending build context to Docker daemon Step 0 : FROM scratch ---> Step 1 : ADD ubuntu-xenial-core-cloudimg-amd64-root.tar.gz /
 ---> 537c2f6dd023 Removing intermediate container dee7679a7ee2 Step 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/initctl Adding '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"; ---> c49bdbf61888 Removing intermediate container 41d719b68981 Step 3 : RUN rm -rf /var/lib/apt/lists/* ---> Running in 6389964016a2 ---> 4508181f7442 Removing intermediate container 6389964016a2 Step 4 : RUN sed -i 's/^#\s*\(deb.*universe\)$/\1/g' /etc/apt/sources.list ---> Running in cbed2b28c988 ---> 8eed06df8f19 Removing intermediate container cbed2b28c988 Step 5 : RUN mkdir -p /run/systemd && echo 'docker' > /run/systemd/container ---> Running in aff40dbc6e05 ---> 19c96e7912a4 Removing intermediate container aff40dbc6e05 Step 6 : CMD /bin/bash ---> Running in 2469ee9d7251 ---> 77e565a65647 Removing intermediate container 2469ee9d7251 Successfully built 77e565a65647 [root@bogon ubuntu-16.04]# docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE ubuntu 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.04
root@5ea0b95e8641:/# cat /etc/issue
Ubuntu 16.04.3 LTS \n \l

root@5ea0b95e8641:/# ps -ef
UID         PID   PPID  C STIME TTY          TIME CMD
root          1      0  0 22:47 ?        00:00:00 /bin/bash
root         11      1  0 22:47 ?        00:00:00 ps -ef
root@5ea0b95e8641:/# 

  其中5ea0b95e8641爲當前容器的ID,進入容器查看全部進程,pid爲1的時bash,linux不該該時init嗎?其實,這就是容器與虛擬機的差異,容器的init進程就是主機上docker服務進程,每一個容器只是一個進程而已。其中的參數-it指的是前端打開並分配一個終端,-d爲在後臺運行,咱們試試當前這個可不可使用-d:

[root@bogon ~]# docker run -d ubuntu:16.04
43ae7ded8e6920b55b8e744b52ffce37b89b25182fcacdc10a5414e6621abff3
[root@bogon ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@bogon ~]# docker run -d ubuntu:16.04 /bin/bash
77f3ec2ebfb3f154772683eeea8ca7e2ba3b7756b1488f5f09818af424e0298e
[root@bogon ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

  能夠明顯的開出來,使用-d後,docker ps查不到任何運行的容器,若是使用-it的話,在別的shell下使用docker ps查看:

[root@bogon ml]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
8341a332c788        ubuntu:16.04        "/bin/bash"         18 seconds ago      Up 18 seconds                           drunk_cori  

  能夠看到,有容器在運行,由於咱們沒有退出。由此能夠看出,容器其實以進程方式運行,執行完成/bin/bash以後,進程消亡,因此容器也就不存在,若是容器裏面是一個tomcat服務,則是另一種狀況了。

  

  基礎鏡像基本構建完成,後面的環境搭建,都將基於這個鏡像構建。

相關文章
相關標籤/搜索