ConoHa VPS 上に Ubuntu 22.04 で Docker が使える環境を整える (2023年12月版)

# この記事で紹介する内容

1. ConoHa VPS を契約する
1. Ubuntu 22.04 のサーバを立てる
1. 安全なSSHログインができる設定を整える
1. Docker が使えるようにする

という手順を紹介します。同様の内容の記事は既に星の数ほどあると思いますが，2023年12月時点での最新の状況に基づいて改めてレポートします。

# ConoHaコントロールパネルにログイン

Conoha VPS のアカウントをまだ持っていなければ，[作りましょう](https://www.conoha.jp/vps/signup/)。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41739/9c937490-73e0-909d-42af-866995260103.png)

そして，[ConoHaコントロールパネルにログイン](https://manage.conoha.jp/Dashboard/)します。

# VPS Ver.3.0 で Ubuntu のサーバを立てる

現在，ConoHa VPS には，Ver.2.0 と Ver.3.0 の2種類のVPSサービスが共存しています。これから新規に作るのであれば，せっかくならば Ver.3 で作っておきましょう。

コントロールパネル左下の `バージョン切替` ボタンを押して，VPS Ver.3.0 に切り替えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41739/d9956877-7689-0077-0fa4-9a9abb9459d1.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41739/cb31e793-78dc-c61b-4102-5f08eddfb7e4.png)

そして，VPS Ver.3.0 になっていることを確認して，`サーバー追加` ボタンを押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41739/4482edad-7e63-41af-167d-a689f1a3cf00.png)

次に，サーバイメージとして `Ubuntu 22.04` を選びます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41739/1b9fa0f0-cc63-7b48-fa88-429c27e1aab0.png)

適当な料金プラン・rootパスワード・ネームタグを決めて，サーバを追加します。しばらく時間がかかった後，Ubuntu 22.04のサーバが追加されます。

# 初期設定

## シリアルコンソールからのログイン

サーバの詳細設定から，コンソールを開きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41739/4968d435-0c83-d861-9d02-6e61c9a2993d.png)

`コンソール` ボタンを押して `シリアル` に切り替えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41739/896f26ab-530f-330b-1bdf-a90eeb74f870.png)

ユーザ名 `root`，パスワードは先程決めたパスワードを入力して，rootログインします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41739/a5bfa44a-c495-db3c-af67-ec29a36f3f92.png)

なお，このブラウザ上のシリアルコンソール使用中によく `Closed` と表示され接続が切れることがあります。そのときは右上の `再読み込み` ボタンを押してください。

## rootユーザ以外のユーザを用意

まずはrootユーザではない管理者ユーザを用意しましょう。ここではユーザ名 `admin` というユーザを用意します。

```sh:［サーバ上のrootで］adminユーザを用意
adduser admin
```

パスワードを設定するように要求されますので，設定します。追加の質問類の答は空でOKです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41739/201c539d-407d-1b0b-8615-1e199097c616.png)

`admin` というユーザを `sudo` 可能なグループに追加し，そちらに切り替えます。

```sh:［サーバ上のrootで］adminユーザをsudo可能とし，ユーザを切り替え
usermod -aG sudo admin
su admin
```

## OSアップデート

`admin` ユーザに切り替えた後，OSのアップデートを適用しておきましょう。
```sh:［サーバ上のadminで］OSアップデート
$ sudo apt update && sudo apt upgrade -y
```

## ホスト名変更

ホスト名をわかりやすい名称に変更しておきましょう。

```sh:［サーバ上のadminで］ホスト名変更
$ sudo vim /etc/hostname
```

ここでは，この内容を `conoha` に変更しておくことにします。

## 再起動

ここまで設定したら，サーバを再起動しましょう。

```sh:［サーバ上のadminで］サーバ再起動
$ sudo reboot
```

# SSHサーバの設定

次に，手元の端末からSSHで安全にログインできるようにしましょう。セキュリティを安全に保つため，次のように設定することにします。

* `root` でのログインは無効化
* 攻撃を受けやすいデフォルトの22番ポートではなく，他のポート番号（ここでは12345とする）に変更する
* パスワードログインを無効化し，公開鍵認証でのみSSHログインできるようにする

## `sshd_config` の設定

まずは，ブラウザ上のシリアルコンソールから，`admin` ユーザでログインします。

そして，`sshd_config` を編集します。

```sh:［サーバ上のadminで］sshd_configの編集
$ sudo vim /etc/ssh/sshd_config
```

次の行を変更します。

```
#Port 22
⬇
Port 12345
```
```
PermitRootLogin yes
⬇
PermitRootLogin no
```

```
#PubkeyAuthentication yes
⬇
PubkeyAuthentication yes
```

```
UsePAM yes
⬇
UsePAM no
```

```
PasswordAuthentication yes
⬇
PasswordAuthentication no
```

## sshd の再起動

`sshd_config` の設定変更を反映させるため，sshd を再起動します。

```sh:［サーバ上のadminで］sshdの再起動
$ sudo systemctl restart ssh.service
```

## 手元の端末で固有の鍵ペアを生成

手元の端末からSSHでログインできるようにするため，手元の端末の公開鍵を登録します。そのための鍵ペアを作っていなければ，事前に生成しておきましょう。

新規に作るのであれば，暗号アルゴリズムとしては，RSA ではなくより安全な ED25519 を採用するべきでしょう。

Unix系OSであれば，`ssh-keygen` コマンドがあるはずですので，それで ED25519 の鍵ペアを生成します。

```sh:［クライアント上で］手元の端末でED25519の鍵ペアを生成
$ ssh-keygen -t ed25519
```

途中でパスフレーズの設定が要求されます。空でもよいですが，設定しておけばより安全でありましょう。

鍵ペアが生成されたことを確認します。

```sh:［クライアント上で］鍵ペアの存在確認
$ ls -l ~/.ssh
```

これで，

* `id_ed25519`：秘密鍵
* `id_ed25519.pub`：公開鍵

が生成されていれば成功です。秘密鍵は決してどこにも公開しないようにしてください。

## VPS上のSSHサーバに接続可能なクライアント公開鍵を登録する

ブラウザのシリアルコンソールで `admin` ユーザでログインし，`admin` ユーザとしてSSH接続を受け付けるクライアント公開鍵を登録しましょう。まずは，`~/.ssh/authorized_keys` を生成し，適切なパーミッションを設定します。

```sh:［サーバ上のadminで］~/.ssh/authorized_keys を生成
$ mkdir ~/.ssh
$ cd ~/.ssh
$ chmod 700 .
$ touch authorized_keys
$ chmod 600 authorized_keys
```

次にクライアント公開鍵をクリップボードにコピーします。macOSならば，`pbcopy` コマンドが使えます。

```sh:［クライアント上で］公開鍵をクリップボードにコピー
$ pbcopy < ~/.ssh/id_ed25519.pub 
```

これをサーバ上の `authorized_keys` に流し込みます。

```sh:［サーバ上のadminで］接続クライアントの公開鍵を登録
$ echo （公開鍵の内容をペースト） >> ~/.ssh/authorized_keys
```

他にも接続したい端末がある場合，同様にして次々に `authorized_keys` に流し込んで登録します。

## Ubuntuのファイアウォール設定変更

デフォルトでは，Ubuntu のファイアウォール `ufw` において，`22/tcp` のみインバウンド通信の許可設定がなされています。これを，`12345/tcp` に変更しましょう。

### ファイアウォールの現状確認

```sh:［サーバ上のadminで］ファイアウォールの現状確認
$ sudo ufw status verbose
Status: Active
Logging: on (low)
Default: reject (incoming), allow (outgoing), disabled (routed)
New profiles: skip

To                         Action      From
--                         ------      ----
22/tcp (OpenSSH)           ALLOW IN    Anywhere
22/TCP (OpenSSH (v6))      ALLOW IN    Anywhere (v6)
```

### 既存ルールの削除

```sh:［サーバ上のadminで］ルールを番号で表示
$ sudo ufw status numbered
Status: Active

     To                         Action      From
     --                         ------      ----
[ 1] OpenSSH                    ALLOW IN    Anywhere
[ 2] OpenSSH (v6)               ALLOW IN    Anywhere (v6)
```

これらのルールを削除しましょう。

```sh:［サーバ上のadminで］既存ルールを削除
$ sudo ufw delete 2
$ sudo ufw delete 1
```

### 新規ルール登録

`12345/tcp` の受信許可設定を加えます。

```sh:［サーバ上のadminで］12345/tcp を許可
$ sudo ufw allow 12345/tcp
Rule added
Rule added (v6)
```

ルールにマッチしない場合のデフォルト設定は `deny` にしておきます。

```sh:［サーバ上のadminで］ファイアウォールのデフォルトをdenyに
$ sudo ufw default deny
```

結果を確認します。

```sh:［サーバ上のadminで］ファイアウォールの現状確認
$ sudo ufw status verbose
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip

To                         Action      From
--                         ------      ----
12345/tcp                  ALLOW IN    Anywhere
12345/tcp (v6)             ALLOW IN    Anywhere (v6)
```

## ConoHa側でのファイアウォール設定変更

Ubuntu内部のファイアウォールだけでなく，ConoHa側にもファイアウォールがありますので，そちらも変更します。

まず，ConoHaコントロールパネルの「セキュリティグループ」の設定で，自分のサーバ用のセキュリティグループを新規作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41739/f6f53341-d94e-4c7f-6ae7-20aa05b74c38.png)

そして，`12345/tcp` を全IPアドレスから受信許可します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41739/386fb409-3d4f-c6ca-0aaa-89e2afd7df66.png)

そして，自分のサーバのセキュリティグループに，新しく作ったセキュリティグループを追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41739/9453b94a-37b4-f7bc-2e29-a30f3054fb52.png)


## クライアントからのSSH接続

### SSH接続確認

この時点で，公開鍵を登録したクライアントからのSSH接続が確立できる状況になっているはずです。試してみましょう。ConoHaのコントロールパネルに表示されている，自分のサーバのIPアドレス `XXX.XXX.XXX.XXX` を調べておいて，ポート指定して接続します。

```sh:［クライアント上で］sshでConoHa VPSサーバにadminユーザで接続
$ ssh -p 12345 admin@XXX.XXX.XXX.XXX
```

これでログインできれば，SSH設定は成功したことになります。

### SSHクライアント側のエイリアス登録

クライアントからエイリアス名で登録しておくと便利です。例えば，自分の端末の `~/.ssh/config` に，次のように `__conoha` という名前のエイリアスとして登録しておきましょう[^1]。IPv4アドレスではなくホスト名で登録しておけば，IPv4とIPv6の両方に対応できます。割り当てられたホスト名は，ConoHaのコントロールパネルの「VPS設定」のところで見つけられます。

[^1]: 自分は「エイリアス名は `__` から始める」というネーミングルールを採用しています。

```ssh:［クライアント上の］~/.ssh/config
Host __conoha
    User admin
    Hostname vXXX-XXX-XXX-XXX.fxcu.static.cnode.jp
    Port 12345
    PreferredAuthentications publickey
    IdentityFile ~/.ssh/id_ed25519
    IdentitiesOnly yes
```

このように設定しておけば，

```sh:［クライアント上で］エイリアス名を用いてConoHa VPSへssh接続
$ ssh __conoha
```

という簡単なコマンドにより，一撃で Conoha VPS の `admin` ユーザにsshログインすることができて便利になります。

# Docker のセットアップ

## Docker のインストール
[Dockerの公式サイトの説明](https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository)に基づき，aptによってDockerエンジンをインストールします。

2023年12月時点では，次のようにアナウンスされていましたので，これに従ってインストールすることにします。

⬇所々対話的にキー入力が要求されるので，一度に全部コピペせず，1行ずつコピペするのがよいです。

```sh:［サーバ上のadminで］Dockerをインストール
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

# Add the repository to Apt sources:
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update

# Install the latest version
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
```

## Docker のテスト実行

Docker が正しくインストールできているかを確かめるため，`hello-world` を取得・実行してみましょう。

```sh:［サーバ上のadminで］Dockerをテスト実行
$ sudo docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
719385e32844: Pull complete 
Digest: sha256:c79d06dfdfd3d3eb04cafd0dc2bacab0992ebc243e083cabe208bac4dd7759e0
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.
（後略）
```

## Docker の sudo を不要に

Docker を `sudo` なしで実行できるよう，現在のユーザを `docker` グループに登録しておくと便利です。

```sh:［サーバ上のadminで］現在のユーザをdockerグループに追加
$ sudo usermod -aG docker $USER
```

一度SSH接続を終了し，再ログインした上で，`sudo` なしでの Docker 実行を試してみます。

```sh:［再接続したサーバ上のadminで］Dockerをsudoなしでテスト実行
$ docker run hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.
（後略）
```

となれば成功です！