如何自行建立一個帶有SSH服務的鏡像,并詳細介紹了兩種建立容器的方法:基于docker commit指令建立和基于Dockerfile建立。
Docker提供了docker commit指令,支援使用者送出自己對制定容器的修改,并生成新的鏡像。
指令格式為docker commit CONTAINER [REPOSITORY[:TAG]]。
這裡以ubuntu:14.04鏡像添加SSH服務的操作流程為例。
1.準備工作
首先,使用ubuntu:14.04鏡像來建立一個容器:
$ docker run -it ubuntu:14.04 /bin/bash
更新apt緩存,并安裝openssh-server:
root@fc1936ea8ceb:/# apt-get update; apt-get install openssh-server -y
2.安裝和配置SSH服務
選擇主流的openssh-server作為服務端:
root@fc1936ea8ceb:/# apt-get install openssh-server –y
如果需要正常啟動SSH服務,則目錄/var/run/sshd必須存在,手動建立它,并啟動SSH服務:
root@fc1936ea8ceb:/# mkdir -p /var/run/sshd
root@fc1936ea8ceb:/# /usr/sbin/sshd -D & [1] 3254
此時檢視容器的22端口(SSH服務預設監聽的端口),可見此端口已經處于監聽狀态:
root@fc1936ea8ceb:/# netstat -tunlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN -
tcp6 0 0 :::22 :::* LISTEN -
修改SSH服務的安全登入配置,取消pam登入限制:
root@fc1936ea8ceb:/# sed -ri 's/session required pam_loginuid.so/#session required pam_loginuid.so/g' /etc/pam.d/sshd
在root使用者目錄下建立.ssh目錄,并複制需要登入的公鑰資訊(一般為本地主機使用者目錄下的.ssh/id_rsa.pub檔案,可由ssh-keygen-t rsa指令生成)到authorized_keys檔案中:
root@fc1936ea8ceb:/# mkdir root/.ssh
root@fc1936ea8ceb:/# vi /root/.ssh/authorized_keys
建立自動啟動SSH服務的可執行檔案run.sh,并添加可執行權限:
root@fc1936ea8ceb:/# vi /run.sh
root@fc1936ea8ceb:/# chmod +x run.sh
其中,run.sh腳本内容如下:
最後,退出容器:
root@fc1936ea8ceb:/# exit
exit
3.儲存鏡像
将所退出的容器用docker commit指令儲存為一個新的sshd:ubuntu鏡像:
$ docker commit fc1 sshd:ubuntu
7aef2cd95fd0c712f022bcff6a4ddefccf20fd693da2b24b04ee1cd3ed3eb6fc
使用docker images檢視本地生成的新鏡像sshd:ubuntu,目前擁有的鏡像如下:
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
sshd ubuntu 7aef2cd95fd0 10 seconds ago 255.2 MB
busybox latest e72ac664f4f0 3 weeks ago 2.433 MB
ubuntu latest ba5877dc9bec 3 months ago 192.7 MB
4.使用鏡像
啟動容器,并添加端口映射10022-->22。其中10022是宿主主機的端口,22是容器的SSH服務監聽端口:
$ docker run -p 10022:22 -d sshd:ubuntu /run.sh
3ad7182aa47f9ce670d933f943fdec946ab69742393ab2116bace72db82b4895
啟動成功後,可以在宿主主機上看到容器運作的詳細資訊:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3ad7182aa47f sshd:ubuntu "/run.sh" 2 seconds ago Up 2 seconds 0.0.0.0:10022->22/tcp focused_ptolemy
在宿主主機(192.168.1.200)或其他主機上上,可以通過SSH通路10022端口來登入容器:
$ ssh 192.168.1.200 -p 10022
root@3ad7182aa47f:~#
使用Dockerfile來建立一個支援SSH服務的鏡像。
1.建立工作目錄
首先,建立一個sshd_ubuntu工作目錄:
$ mkdir sshd_ubuntu
在其中,建立Dockerfile和run.sh檔案:
$ cd sshd_ubuntu/
$ touch Dockerfile run.sh
2.編寫run.sh腳本和authorized_keys檔案
腳本檔案run.sh的内容:
在宿主主機上生成SSH密鑰對,并建立authorized_keys檔案:
$ ssh-keygen -t rsa
$ cat ~/.ssh/id_rsa.pub > authorized_keys
3.編寫Dockerfile
下面是Dockerfile的内容及各部分的注釋,可以對比上一節中利用docker commit指令建立鏡像過程,所進行的操作基本一緻:
4.建立鏡像
在sshd_ubuntu目錄下,使用docker build指令來建立鏡像。這裡需要注意最後還有一個“.”,表示使用目前目錄中的Dockerfile:
$ cd sshd_ubuntu
$ docker build -t sshd:Dockerfile .
使用Dockerfile建立自定義鏡像,需要注意的是Docker會自動删除中間臨時建立的層,還需要注意每一步的操作和編寫的Dockerfile中指令的對應關系。
指令執行完畢後,如果見“Successfully built XXX”字樣,則說明鏡像建立成功。可以看到,以上指令生成的鏡像ID是570c26a9de68。
在本地檢視sshd:Dockerfile鏡像已存在:
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
sshd Dockerfile 570c26a9de68 4 minutes ago 246.5 MB
ubuntu 14.04 ba5877dc9bec 3 months ago 192.7 MB
5.測試鏡像,運作容器
使用剛才建立的sshd:Dockerfile鏡像來運作一個容器。
直接啟動鏡像,映射容器的22端口到本地的10122端口:
$ docker run -d -p 10122:22 sshd:Dockerfile
890c04ff8d769b604386ba4475253ae8c21fc92d60083759afa77573bf4e8af1
在宿主主機新打開一個終端,連接配接到建立的容器:
$ ssh 192.168.1.200 -p 10122
root@890c04ff8d76:~#
效果與上一小節一緻,鏡像建立成功。
在Docker社群中,對于是否需要為Docker容器啟用SSH服務一直有争論。
反對方的觀點是:Docker的理念是一個容器隻運作一個服務。是以,如果每個容器都運作一個額外的SSH服務,就違背了這個理念。另外認為根本沒有從遠端主機進入容器進行維護的必要。
支援方的觀點是:在Docker 1.3版本之前,如果要用attach進入容器,經常容易出現卡死的情況。1.3之後,雖然官方推出了docker exec指令,再從宿主主機進入是沒有障礙了,但是如果要從其他遠端主機進入容器依然沒有更好的解決方案。
這兩種說法各有道理,其實是在讨論不同的容器場景:即作為應用容器還是作為系統容器。應用容器行為圍繞應用生命周期,較為簡單,不需要人工的額外幹預;而系統容器則需要支援管理者的登入操作,這個時候,對SSH服務的支援就變得十分必要了。
是以,在Docker推出更加高效、安全的方式對系統容器進行遠端操作之前,容器的SSH服務還是比較重要的,而且它對資源的需求不高,同時安全性可以保障。