天天看點

為鏡像添加SSH服務

如何自行建立一個帶有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服務還是比較重要的,而且它對資源的需求不高,同時安全性可以保障。