###### tags: `tutorials` `ubuntu` `linux` `SSH` `docker`
# 建立一個可以 SSH 連線的 docker container
:::success
可以透過
- 修改 `Dockerfile`
- ***或是*** 建立好 container 後再進入 container 中安裝
:::
## By docker file
### Add to `Dockerfile`
在 `Dockerfile` <font color=red>***最後***</font> 加入以下程式碼在最後片段
``` !
# ssh setting
RUN echo "$ssh_usr:$ssh_pwd" >> ~/passwdfile && \
chpasswd -c SHA512 < ~/passwdfile && \
rm ~/passwdfile && \
sed -i "s/#Port.*/Port 22/" /etc/ssh/sshd_config && \
sed -i "s/#PermitRootLogin.*/PermitRootLogin yes/" /etc/ssh/sshd_config && \
sed -i "s/#PasswordAuthentication.*/PasswordAuthentication yes/" /etc/ssh/sshd_config
# expose the port 22(which is the default port of ssh)
EXPOSE 22
# set entrypoint to restart ssh automatically
ENTRYPOINT service ssh restart && bash
```
:::warning
預設會自動啟動 `SSH` (藉由最後面的 `ENTRYPOINT`)
:::
### Run container
在 `docker run` contianer 時,加入 `-p {remote_container_port}:{container_ssh_port}` 來設定連到 container 的 port
- `-p`: 設定 local<->container 的 port mapping
- {remote_container_port}: 外部連線的 port
- {container_ssh_port}: container 內部的 SSH 設定 port
:::info
例如 `docker run -it --name test -p 5678:22 -d test_img` 就是用 `test_img` 的 image 建立一個名字叫做 `test` 的 container,並且將 container 外部(就是 local)的 *5678* port 對應到 container 內部的 port *22*
> container 內部 port(在這個例子是 *22*) 必須要是 container 裡 SSH 設定的 port
:::
> 更多關於 docker 使用可以看[這篇](https://hackmd.io/@jimmy801/docker_usage)
---
## By install SSH after access to container
- Run container 的方式和[上面](#Run-container)一樣
- 進入 container
```bash= !
$ docker exec -it {containerID_or_name} bash
```
- `-it`: 代表在執行 Docker 虛擬容器環境時,開啟虛擬終端機,以互動的模式執行
- {containerID_or_name}: 指定執行的 container ID 或名字
> 以上面的例子來說就是 `test`
- `bash`: 因為要安裝 SSH 所以是以 bash 開啟
- 進入 container 後,安裝 SSH
```bash= !
$ apt-get update && apt-get install -y ssh
```
- 修改 container 內的 SSH config
```bash= !
$ vim /etc/ssh/sshd_config
```
1. 修改 port
文件的前幾行有個 Port 可以設定,預設是 `22`
:::info
這個 port 是對應到[上述](#Run-container)的 `{container_ssh_port}`
:::
2. 修改授權
將文件中的 `PasswordAuthentication XXX` 取消註解並修改成 `PasswordAuthentication yes`
3. 啟用 *root* 登入授權
將文件中的 `PermitRootLogin XXX` 取消註解並修改成 `PermitRootLogin yes`
4. 設定使用者密碼
因為 container 預設使用者是 *root*,而我們也想讓之後連進來的權限為 *root*,但又不想讓任何知道 ip 和 port 的外部人員可以任意連進來,所以需要設定 container 內 *root* 的密碼
```bash= !
$ passwd root
```
5. 重啟 container
設完密碼後需要重啟 container 才會生效
- 離開 container
```bash= !
$ exit
```
- 在 container 外重啟 container
```bash= !
$ docker restart {containerID_or_name}
```
- 重新進入 container 並重啟 SSH 使其生效
- 進入 container
```bash= !
$ docker exec -it {containerID_or_name} bash
```
- 重啟 SSH
```bash= !
$ /etc/init.d/ssh restart
```
:::warning
每次重新啟動 container 後,都必須得進入 container 重新開啟 SSH
:::
> 更多關於 SSH 安裝與設定可以看[這篇](https://hackmd.io/@jimmy801/SSH)
---
## SSH 連線進入 container
以 SSH 連線進剛剛設定的 container 的方式就是以和剛剛 server local 同樣 ip 連線,但 port 使用[一開始](#Run-container)設定的 `{remote_contianer_port}`