前言

在開發 Docker 應用程式時,有時候我們會需要進入到容器內部進行操作,例如查看 log、修改設定檔等等。這時候,我們可以透過 ssh 的方式連接到容器,這樣就不用每次都透過 docker exec 進入容器,更加方便快捷。本章節將會介紹如何在本機透過 ssh 的方式連到 Docker 容器。

步驟

步驟 1:建立 Ubuntu 22.04 的 Docker 容器

我們要使用 host 模式來讓容器共享主機的網路。先拉取 Ubuntu 22.04 輕量版的 Docker image

1
docker pull ubuntu:22.04

運行容器並使用 --network host--network host 讓容器直接使用主機的網路環境,因此不需要手動進行 port mapping。因為 ubuntu:22.04 是一個最小化的 Docker image,預設沒有執行任何長時間運行的程序,所以當 docker run 完成初始化後,容器就會立即退出。所以這裡可以使用 tail -f /dev/null 這會讓容器內一直執行,確保它不會退出。

  • tail 是一個用來查看文件末尾幾行的命令。可以一直監聽文件的變化。
  • -f 參數的意思是「持續監聽」,當文件內容有變更時會即時輸出。
  • /dev/null 是一個特殊的「黑洞」設備,任何寫入它的內容都會被丟棄,讀取它時則永遠是空的。
1
docker run -d --name my_ubuntu --network host ubuntu:22.04 tail -f /dev/null

步驟 2:進入 Container 安裝 OpenSSH

因為 Ubuntu 預設沒有 openssh-server,所以我們要手動安裝。

進入容器

1
docker exec -it my_ubuntu bash

更新套件並安裝 OpenSSH Server

1
apt update && apt install -y openssh-server && apt install -y vim

設定 SSH 允許 root 登入

1
2
echo 'PermitRootLogin yes' >> /etc/ssh/sshd_config
echo 'PasswordAuthentication yes' >> /etc/ssh/sshd_config

建立 root 密碼

1
passwd root

步驟 3:設定 SSH 監聽 2222 port

修改 sshd_config 讓 SSH 監聽 2222

1
sed -i 's/^#Port 22/Port 2222/' /etc/ssh/sshd_config

重新啟動 SSH 服務

1
2
3
4
5
service ssh restart
# 確認 ssh 服務是否正常運行
service --status-all
# 如果顯示 [ + ] ssh 就是正常運行 否則 [ - ] 代表沒有運行
service ssh start

步驟 4:開放主機的防火牆

由於我們使用的是 host 模式,SSH 服務其實是直接運行在你的主機上,因此你需要確保 2222 port 是開放的。

1
2
3
4
5
6
7
8
# 開放 2222 port
ufw allow 2222/tcp

# 啟用防火牆(如果還沒啟用)
ufw enable

# 檢查防火牆規則
ufw status

如果你的主機沒有使用 ufw,而是 iptables,可以執行:

1
2
3
4
sudo iptables -A INPUT -p tcp --dport 2222 -j ACCEPT

# 並存檔以確保重啟後仍生效:
sudo netfilter-persistent save

如何測試 SSH 是否開放?

1
2
3
4
5
6
7
nc -zv <你的主機 IP> 2222

# 如果端口開放,應該會看到:
# Connection to <你的主機 IP> 2222 port [tcp/*] succeeded!

# 或者直接測試 SSH 連線:
ssh root@<你的主機 IP> -p 2222

補充: etc/ssh/sshd_config 設定檔

/etc/ssh/sshd_config 是 OpenSSH 伺服器 (sshd) 的主要設定檔,用於控制 SSH 伺服器的行為。以下是常見的設定項目及其用途:

端口與地址綁定

Port(SSH 服務監聽的端口)

1
Port 22
  • 指定 SSH 伺服器監聽的端口,預設為 22。
  • 例如改成 Port 2222,則 SSH 會監聽 2222。

ListenAddress

1
2
# Listen on all available interfaces
ListenAddress 0.0.0.0
  • 設定 SSH 監聽的 IP,0.0.0.0 代表所有網卡。
  • 例如只允許內部網路:ListenAddress 192.168.1.100

登入驗證相關設定

PermitRootLogin(允許 root 直接登入)

1
PermitRootLogin prohibit-password
  • yes:允許 root 直接 SSH 登入。
  • no:完全禁止 root 登入。
  • prohibit-password(預設值):允許使用 SSH Key 登入,但不允許密碼登入。

PasswordAuthentication(允許密碼登入)

1
PasswordAuthentication yes
  • yes:允許密碼登入。
  • no:強制要求 SSH 金鑰登入(更安全)。

PubkeyAuthentication(允許 SSH Key 登入)

1
PubkeyAuthentication yes
  • yes:允許 SSH Key 登入(推薦)。
  • no:禁止 SSH Key 登入(不建議)。

AuthorizedKeysFile(指定公鑰存放位置)

1
AAuthorizedKeysFile .ssh/authorized_keys
  • 指定公鑰存放的檔案,預設為 ~/.ssh/authorized_keys

多重登入與驗證

1
2
3
4
5
# MaxAuthTries(最大驗證次數)
MaxAuthTries 6

# MaxSessions(最大同時登入數)限制單個 SSH 連線可以開多少個子會話。
MaxSessions 10

安全性相關

1
2
3
4
5
6
7
8
9
10
# AllowUsers / AllowGroups(允許特定使用者登入)
AllowUsers user1 user2
AllowGroups sshusers

# DenyUsers / DenyGroups(禁止特定使用者登入)
DenyUsers user3 user4
DenyGroups sshdenied

# LoginGraceTime(登入寬限時間)SSH 允許登入的時間(秒),超過時間未完成登入則關閉連線。
LoginGraceTime 120

重啟 SSH 服務

1
2
3
4
# 每次修改 sshd_config 後,需要重新啟動 SSH 服務:
service ssh restart
# 或
systemctl restart ssh

參考