Podmanでcode-serverのcontainerを起動しサービスとして公開する方法

# 目的
仕事の中でお客様にワークショップを行うための開発環境を提供する場面があって、検討した結果、
ブラウザでhttpsでvscodeが使えるようにした。メリットは以下です。
- お客様のセキュリティ対策で遮断される可能性が低い
- 開発環境としての利便性が高い
    - extensionをインストールして使い勝手を良くすることができる
- 開発環境の構築内容が自由
    - nodejs、python、事前にインストールするextensionなどContainerfileで自由に変更可能

# 構築方法
## 全体概要図
![drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150479/206b8dbb-dde6-83a6-9878-79d549f01f46.png)

## 前提条件
下記ツールがインストールされていること
- podman
- podman-compose
- podman-desktop(option)

## コンテナ
### カスタマイズしたcode-serverのイメージをビルド
Containerfile
```
FROM lscr.io/linuxserver/code-server:latest
LABEL description="node-16.16.0の実行環境を構築した code-server container image"
LABEL maintainer="author <abc@example.com>"
SHELL ["/bin/bash", "-c"]
RUN git clone https://github.com/anyenv/anyenv ~/.anyenv && \
    echo 'export PATH="$HOME/.anyenv/bin:$PATH"' >> ~/.bashrc && \
    echo 'eval "$(anyenv init -)"' >> ~/.bashrc && \
    source ~/.bashrc && \
    anyenv --version && \
    anyenv install --force-init && \
    anyenv install nodenv && \
    source ~/.bashrc && \
    echo 'eval "$(nodenv init -)"' >> ~/.bashrc && \
    nodenv install 16.16.0 && \
    nodenv global 16.16.0 && \
    /app/code-server/bin/code-server --extensions-dir /config/extensions --install-extension firsttris.vscode-jest-runner && \
    /app/code-server/bin/code-server --extensions-dir /config/extensions --install-extension dracula-theme.theme-dracula
```

`SHELL ["/bin/bash", "-c"]`でbashに切り替えて、anyenvとnodenvを使ってnodeの実行環境を構築する。

最後の2行はvscodeのextensionをインストールしている。
`code-server`だけだと、`command not found`エラーが出るため、フルパス指定した。
また、`--extensions-dir`でextersionのインストール先を指定しないと、webブラウザでログインした後extensionが見つからない事象が生じた。

Containerfileと同じディレクトリで`podman build --format docker --layers=false -t code-server-nodejs16:latest .`を実行すると、カスタムイメージがビルドされる。
`--format docker`を入れた理由は`SHELL ["/bin/bash", "-c"]`を有効にしたいから。このオプションを追加しなければpodmanは`SHELL`を識別しない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150479/2ff98c78-beb0-ac46-2055-a30920204d95.png)

### カスタムイメージのコンテナを起動
code-server.yml(post-composeのファイル)
```yml
---
version: "2.1"
services:
  code-server:
    image: localhost/code-server-nodejs16:latest
    container_name: code-server1
    environment:
      - PUID=0
      - PGID=0
      - TZ=Asia/Tokyo
      - PASSWORD=password #optional
      # - SUDO_PASSWORD=password #optional
      # - SUDO_PASSWORD_HASH= #optional
      # - PROXY_DOMAIN=code-server.my.domain #optional
      - DEFAULT_WORKSPACE=/config/workspace #optional
    # volumes:
    #   - ./config:/config
    ports:
      - 8443:8443
    restart: unless-stopped
```
environmentの各環境変数の意味は[こちら](https://hub.docker.com/r/linuxserver/code-server)をご参考ください。

`podman-compose -f code-server.yml up -d`を実行すると、コンテナが起動される。
複数起動したい場合はcode-server.ymlをコピーして、container_nameとportsの設定を変更すればいい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150479/6f81ee02-81da-8160-40ee-c49413b8c0b2.png)

### 動作確認
`http://localhost:8443`にアクセスしてパスワードを入力すれば、下記画面が表示される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150479/6df2ce31-98cd-1633-a9fb-01ad5ece0564.png)

### サンプルコード
https://github.com/coolboy0961/code-server
*今後記事の内容と合わなくなるくらい変更していく可能性あり*

## SSL証明書およびリバースプロキシ
### 前提条件
- SynologyのNASを所有していること
- 外からhttpsでNASのWeb Console画面にアクセスできていること

### リバースプロキシの設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150479/8647e7f5-97da-ca0c-2c75-e6da6e12cae3.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150479/22167a15-02b2-8f7a-9df9-33a4d51b4dae.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150479/b52be6b4-fc87-4812-26d9-c21e4722ab94.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150479/a2d8a55d-90c4-22c7-3ddb-eba9aa9bd3fc.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150479/a3e756e6-190e-6d39-1ebf-dcad5d20c8a8.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150479/44fca5c7-b6a1-be66-3f2d-b5b231b979e5.png)

リバースプロキシにWebSocketのサポートを追加しなければ、リバースプロキシ経由でcode-serverに繋げると`1006`エラーが発生する。
詳細は[こちら](https://github.com/microsoft/vscode-remote-release/issues/7163)をご参考ください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150479/0bb68e27-203c-1ed2-b2e7-647e6e59b134.png)


### SSL証明書の発行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150479/78e0f5b9-1335-fe35-b1a9-7f31a79138ad.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150479/60f16397-98eb-ee9b-0516-16ce22840d19.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150479/7a607ba4-335b-f063-bb8f-d239b57a14c9.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150479/da9324c9-b9d5-c593-7e1a-db994901059c.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150479/de03c4fc-c567-1d5c-575e-240181333954.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150479/e38fa953-b1b1-81ac-55ed-dce183f084cb.png)
リバースプロキシの設定と証明書を紐づける設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150479/70aba020-f7dc-918d-1e89-d1f4daed0dbf.png)


### 動作確認
動作確認時に`Error code: SSL_ERROR_BAD_CERT_DOMAIN`がブラウザで表示されたら、しばらく待ってからブラウザを開き直したりして再度確認してみてください。
リバースプロキシの設定と証明書を紐づける設定を反映するのに時間がかかる場合がある。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150479/03586629-226f-ded2-1f00-132bdb95f1c1.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150479/220ea88f-a503-bc11-509f-31e5b8e60496.png)

## まとめ
以上、Podmanでcode-serverのcontainerを起動しサービスとして公開する方法でした。
*同じ記事を[赤帽エンジニアブログ](https://rheb.hatenablog.com/entry/2022/09/13/152350)にも記載してあります。*