操作Docker容器介紹了一些進入容器的辦法,比如attach、exec等命令,但是這些命令都無法解決遠程管理容器的問題。因此,當需要遠程登錄到容器內進行一些操作的時候,就需要SSH的支持了。
如何自行創建一個帶有SSH服務的鏡像,並詳細介紹了兩種創建容器的方法:基於docker commit命令創建和基於Dockerfile創建。
基於commit命令創建
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腳本內容如下:
#!/bin/bash /usr/sbin/sshd -D
最后,退出容器:
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創建
使用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的內容:
#!/bin/bash /usr/sbin/sshd -D
在宿主主機上生成SSH密鑰對,並創建authorized_keys文件:
$ ssh-keygen -t rsa
$ cat ~/.ssh/id_rsa.pub > authorized_keys
3.編寫Dockerfile
下面是Dockerfile的內容及各部分的注釋,可以對比上一節中利用docker commit命令創建鏡像過程,所進行的操作基本一致:
#設置繼承鏡像 FROM ubuntu:14.04 #提供一些作者的信息 MAINTAINER docker_user (user@docker.com) #下面開始運行更新命令 RUN apt-get update #安裝ssh服務 RUN apt-get install -y openssh-server RUN mkdir -p /var/run/sshd RUN mkdir -p /root/.ssh #取消pam限制 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"]
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
$ docker ps
在宿主主機新打開一個終端,連接到新建的容器:
$ 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服務還是比較重要的,而且它對資源的需求不高,同時安全性可以保障。