docker鏡像的創建commit及dockerfile


在docker 1.3版本以前使用attach進入容器會經常出現卡死的情況,之后官方退出了exec命令,從宿主機進入,但是從其他遠程主機進入使用ssh服務來維護是用戶熟悉的方法。所以這里來創建一個帶有ssh服務的鏡像。基於docker commit命令和dockerfile創建。

 

基於commit命令

commit命令格式為docker commit CONTAINER [REPOSITORY[:TAG]],用戶提交對容器的修改,並生成新的鏡像。

 

首先使用ubuntu鏡像來創建一個容器,嘗試使用ssh命令無效。

# docker run -it ubuntu /bin/bash

 

因為ubuntu官方鏡像中沒有軟件包的緩存文件,使用apt-get update更新即可,也可以修改源來配置。然后安裝ssh。

# apt-get update

# apt-get install ssh -y

 

運行ssh需要目錄/var/run/sshd存在,創建啟動服務

# mkdir -p /var/run/sshd

# /usr/sbin/sshd -D &

然后可以看到已經運行,netstat命令可能也沒有,安裝即可apt-get install net-tools

 

此處還需要修改ssh服務的安全登錄配置,取消pam登錄限制,如下圖注釋即可。

 

然后復制需要登錄的公鑰信息(這里為本地主機)。使用ssh-keygen可以生成。

復制id_rsa.pub的內容到容器中的/root/.ssh/authorized_keys

 

創建ssh服務執行文件,然后退出容器

# vim /run.sh

# chmod +x run.sh

 

使用docker commit保存修改的容器,然后運行

# docker commit CONTAINER ID ssh:ubuntu

# docker run -d -p :22 ssh:ubuntu /run.sh

 

最后可以在宿主機上通過隨機生成的32779端口來訪問登錄容器了:

 

使用dockerfile創建鏡像

創建一個目錄sshd_ubuntu,分別創建文件如下:

authorized_keys文件內容同樣的復制

# cat /root/.ssh/id_rsa.pub > authorized_keys

 

然后編寫Dockerfile文件如下,源自行修改即可:

 

FROM ubuntu:latest

 

MAINTAINER from whychz@ubuntu.com by boss yan

 

RUN rm -rf /etc/apt/sources.list

 

RUN echo 'deb-src http://archive.ubuntu.com/ubuntu xenial main restricted' >> /etc/apt/sources.list

RUN echo 'deb http://mirrors.aliyun.com/ubuntu/ xenial main restricted' >> /etc/apt/sources.list

RUN echo 'deb-src http://mirrors.aliyun.com/ubuntu/ xenial main restricted multiverse universe' >> /etc/apt/sources.list

RUN echo 'deb http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted' >> /etc/apt/sources.list

RUN echo 'deb-src http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted multiverse universe' >> /etc/apt/sources.list

RUN echo 'deb http://mirrors.aliyun.com/ubuntu/ xenial universe' >> /etc/apt/sources.list

RUN echo 'deb http://mirrors.aliyun.com/ubuntu/ xenial-updates universe' >> /etc/apt/sources.list

RUN echo 'deb http://mirrors.aliyun.com/ubuntu/ xenial multiverse' >> /etc/apt/sources.list

RUN echo 'deb http://mirrors.aliyun.com/ubuntu/ xenial-updates multiverse' >> /etc/apt/sources.list

RUN echo 'deb http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse' >> /etc/apt/sources.list

RUN echo 'deb-src http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse' >> /etc/apt/sources.list

RUN echo 'deb http://archive.canonical.com/ubuntu xenial partner' >> /etc/apt/sources.list

RUN echo 'deb-src http://archive.canonical.com/ubuntu xenial partner' >> /etc/apt/sources.list

RUN echo 'deb http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted' >> /etc/apt/sources.list

RUN echo 'deb-src http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted multiverse universe' >> /etc/apt/sources.list

RUN echo 'deb http://mirrors.aliyun.com/ubuntu/ xenial-security universe' >> /etc/apt/sources.list

RUN echo 'deb http://mirrors.aliyun.com/ubuntu/ xenial-security multiverse' >> /etc/apt/sources.list

 

RUN apt-get update

RUN apt-get install -y openssh-server

RUN mkdir -p /var/run/sshd

RUN mkdir -p /root/.ssh

 

RUN sed -ri 's/session required pam_loginuid.so/#session required pam_loginuid.so/g' /etc/pam.d/sshd

 

ADD authorized_keys /root/.ssh/authorized_keys

ADD run.sh /run.sh

RUN chmod 755 /run.sh

 

EXPOSE 22

 

CMD ["/run.sh"]

 

 

然后使用docker build創建鏡像。最后的"."(點)表示當前目錄中的Dockerfile

# docker build -t ubuntu:sshserver .

執行完成之后docker images查看鏡像

 

最后運行容器,ssh測試是否成功

# docker run -d -p :22 ubuntu/sshserver --name ssh

# ssh 192.168.2.189 -p 32782 可以看到通過ssh已經進來了容器

 

 

Dockerfile介紹

Dockerfile是一個文本格式的配置文件,可以使用Dockerfile快速創建自定義的鏡像。

基本結構

Dockerfile由一行行命令語句組成,支持#注釋。一般分為四個部分:基礎鏡像,維護者信息,鏡像操作指令和容器啟動時執行指令。

一開始必須指明所基於的鏡像,接下來會說明維護者信息。后面則是鏡像的操作,比如RUN指令,每運行一條,鏡像會添加新的一層,並提交。最后是CMD指令,來指定運行容器時的操作命令。

 

指令

FROM

格式為 FROM <image>或 FROM <image>:tag。指明所基於的鏡像。

必須為第一條指令,如果在一個Dockerfile文件里創建多個鏡像可多次使用,每個鏡像一次。

 

MAINTAINER

格式為 MAINTAINER <name>,指定維護者信息

 

RUN

運行指定的命令

RUN命令有兩種格式

1. RUN <command>

2. RUN ["executable", "param1", "param2"]

第一種后邊直接跟shell命令,在linux操作系統上默認 /bin/sh -c。第二種是類似於函數調用。

可將executable理解成為可執行文件,后面就是兩個參數。

 

兩種寫法比對:

RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME

RUN ["/bin/bash", "-c", "echo hello"]

注意:多行命令不要寫多個RUN,原因是Dockerfile中每一個指令都會建立一層。

多少個RUN就構建了多少層鏡像,會造成鏡像的臃腫、多層,不僅僅增加了構件部署的時間,還容易出錯。RUN書寫時的換行符是\

 

CMD

容器啟動時要運行的命令

 

語法有三種格式

1. CMD ["executable","param1","param2"] 使用exec執行,推薦方式

2. CMD ["param1","param2"] 提供給ENTRYPOINT默認參數

3. CMD command param1 param2 在/bin/sh中執行,提供需要交互的應用

舉例說明兩種寫法:

CMD [ "sh", "-c", "echo $HOME"]

CMD [ "echo", "$HOME" ]

這里邊包括參數的一定要用雙引號,不能是單引號。原因是參數傳遞后,docker解析的是一個JSON array。

每個dockerfile只能有一條CMD命令。指定了多條就只有最后一條會被執行。如果啟動容器時候制定了運行的命令,則也會覆蓋掉CMD指定的命令。

 

 

EXPOSE

格式為EXPOSE <port>[<port>...]

例如:EXPOSE 22 80 433

告訴docker服務器容器暴露的端口號

 

ENV

格式為ENV<key><value>

指定環境變量,會被后續的RUN指令使用,並在容器內保持運行

 

ADD

格式為<src><dest>

將指定的<src>到容器中的<dest>。<src>可以是dockerfile所在目錄的一個相對路徑,可以是一個url,也可以是一個tar文件(自動解壓為目錄)

 

COPY

又是一個復制命令

語法如下:

1. COPY <src>... <dest>

2. COPY ["<src>",... "<dest>"]

與ADD的區別是COPY的<src>只能是本地文件,其他用法一致

 

ENTRYPOINT

格式為:

1. ENTRYPOINT ["executable", "param1", "param2"]

2. ENTRYPOINT command param1 param2

配置容器啟動后執行的命令,不可被docker run覆蓋。每個Dockerfile中只能有一個ENTRTPOINT,指定多個時,只有最后一個生效。

 

VOLUME

格式為:

VOLUME ["/data"]

可實現掛載功能,可以將內地文件夾或者其他容器種得文件夾掛在到這個容器種

["/data"]可以是一個JsonArray ,也可以是多個值。所以如下幾種寫法都是正確的

VOLUME ["/var/log/"]

VOLUME /var/log

VOLUME /var/log /var/db

一般的使用場景為需要持久化存儲數據時

容器使用的是AUFS,這種文件系統不能持久化數據,當容器關閉后,所有的更改都會丟失,所以當數據需要持久化時用這個命令。

 

USER

設置啟動容器的用戶,可以是用戶名或UID,下面的兩種寫法是正確的:

USER daemo

USER UID

如果設置了容器以daemon用戶去運行,那么RUN, CMD 和 ENTRYPOINT 都會以這個用戶去運行。也可以在之前創建所需要的用戶,如:RUN useradd user1,臨時獲取權限不推薦sudo而使用gosu。

 

WORKDIR

格式:WORKDIR /path/to/workdir

對后續的RUN,CMD,ENTRYPOINT,COPY,ADD配置工作目錄。如果不存在則會創建,也可以設置多次

如:

WORKDIR /a

WORKDIR b

WORKDIR c

RUN pwd

結果是/a/b/c

 

WORKDIR也可以解析環境變量

 

如:

ENV DIRPATH /path

WORKDIR $DIRPATH/$DIRNAME

RUN pwd

pwd的執行結果是/path/$DIRNAME

 

ONBUILD

格式:ONBUILD [INSTRUCTION]

這個命令只對當前鏡像的子鏡像生效。

 

比如當前鏡像為A,在Dockerfile種添加:

ONBUILD RUN ls -al

這個 ls -al 命令不會在A鏡像構建或啟動的時候執行,但是如果有一個鏡像B是基於A鏡像構建的,那么這個ls -al 命令會在B鏡像構建的時候被執行。

 

 

鏡像的創建

docker build [path],命令會讀取指定路徑下的Dockerfile,並將該路徑下所有內容發送給Docker服務端,由服務端來創建鏡像。因此建議一般放置Dockerfile目錄為空目錄。指定鏡像的標簽信息使用-t選項。如上面例子的docker build -t ubuntu:sshserver .

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM