在docker 1.3版本之前使用attach進入容器會常常出現卡死的狀況,以後官方退出了exec命令,從宿主機進入,可是從其餘遠程主機進入使用ssh服務來維護是用戶熟悉的方法。因此這裏來建立一個帶有ssh服務的鏡像。基於docker commit命令和dockerfile建立。 linux
commit命令格式爲docker commit CONTAINER [REPOSITORY[:TAG]],用戶提交對容器的修改,並生成新的鏡像。 docker
首先使用ubuntu鏡像來建立一個容器,嘗試使用ssh命令無效。 shell
# docker run -it ubuntu /bin/bash ubuntu
由於ubuntu官方鏡像中沒有軟件包的緩存文件,使用apt-get update更新便可,也能夠修改源來配置。而後安裝ssh。 vim
# apt-get update 緩存
# apt-get install ssh -y 安全
運行ssh須要目錄/var/run/sshd存在,建立啓動服務 bash
# mkdir -p /var/run/sshd 服務器
# /usr/sbin/sshd -D & session
而後能夠看到已經運行,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端口來訪問登陸容器了:
建立一個目錄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由一行行命令語句組成,支持#註釋。通常分爲四個部分:基礎鏡像,維護者信息,鏡像操做指令和容器啓動時執行指令。
一開始必須指明所基於的鏡像,接下來會說明維護者信息。後面則是鏡像的操做,好比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 .