RockyLinux8環境上でSquid on dockerを試す

# はじめに
諸事情でRockyLinux8ベースにSquidコンテナを立てる(docker)テストが必要となった。
自宅にある一番パワーの余ったPCはWindows10Pro環境であったため、Hyper-V上でなるべく手間をかけずに環境を作り、起動テストを行う。

* 目的と制約
    * Squidを動かすこと
    * SquidはSSL Bump可能な状態とすること
    * コンテナ(Docker)でSquidを起動すること
    * ホストOSはRockyLinux8であること

# Hyper-V準備
ググったら出てくるサイトを参考にHyper-Vマネージャーを起動する。
詳細は略すがポイントは以下の通り。

* [タスクマネージャー] -> [パフォーマンス]タブ -> [CPU] 仮想化：有効　になっていること
* [Windowsキー]+ R -> 「OptionalFeatures.exe」-> [Hyper-V] 配下すべてチェックが入っていること
* スタート -> [Hyper-V マネージャ]をクリックして起動する

# Rocky Linux 8準備
RockyLinuxホームページよりBoot imageを入手
 https://rockylinux.org/ja/download
 x86_64 -> Boot

**Hyper-V マネージャーを起動し仮想マシンを新規作成する**
1. [新規] -> [仮想マシン(M)]
1. [名前] -> 適宜設定
1. [世代の指定] -> 第1世代(1)
1. [メモリの割り当て] -> 適宜設定。今回のテスト環境では 2048MB とした
1. [ネットワークの構成] -> DefautSwitch を選択。勝手に外部へ出れるはず
1. [仮想ハードディスクの接続] -> 基本デフォルトだが、サイズだけ 32GB へ
    * [インストール オプション] -> ブート CD/DVD-ROM からオペレーティング システムをインストールする -> イメージファイル(.iso) -> 先ほどDLした Rocky-8.X-x86_64-boot.iso を選択
1. [完了] -> 仮想マシンを起動する

**RockyLinux8 Boot.imgからMinimalインストール**
1. 起動するとBoot imageを読み込みインストーラ画面になるため、 Install Rocky Linux を選択
1. [言語]：日本語　を選択
1. [ネットワーク設定]：インターフェースが無効になっているためクリックで有効化する
1. [インストール設定]：リポジトリは近隣のミラーが自動設定される。最小構成オプション無しを選択
1. root パスワードを設定
1. User / Userパスワードを設定。管理者権限を付与する（sudo 可になる）
1. [完了] -> インストールが終わると再起動ボタンをクリックして Hyper-V上にRockyLinux8 が動作することを確認

**環境設定補足**
```shell-session
＃日本語設定
$ sudo localectl set-locale LANG=ja_JP.utf8

＃タイムゾーン設定
$ sudo timedatectl set-timezone Asia/Tokyo
```

# Docker環境準備
```shell-session
$ sudo dnf update
$ sudo dnf upgrade
 
$ sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
$ sudo dnf install -y docker-ce docker-ce-cli containerd.io

$ sudo systemctl start docker
$ sudo systemctl enable docker
```

# Dockerfileを作成
* 当初 Ubuntu22.04イメージにSquidをインストールしようと考えていたがAlpine imageで目的が達成できることがわかったためAlpineを使う

```shell-session
$ cd ~/alpine_squid2/
$ vi Dockerfile
```

* Dockerfile
    * RUN -> squidパッケージインストールと後に備えてdefaultのsquid.conf削除
    * COPY① -> あらかじめ準備したdev_squid.conf をsquid.confとしてコンテナ配置
    * COPY② -> execute.shをコンテナ配置（説明は次）
    * CMD -> execute.sh内で /usr/sbin/squid を起動
``` docker
FROM alpine:3.17

RUN apk add --no-cache squid && \
    rm -rf /etc/squid/squid.conf

COPY ./conf/dev_squid.conf /etc/squid/squid.conf
COPY execute.sh /execute.sh

CMD ["/execute.sh"]
```
* execute.sh
    * access.logをstdoutへ出力するため、コンテナ起動後に/dev/stdoutの権限を変更
```shell-session
#!/bin/sh

chown squid:squid /dev/stdout

/usr/sbin/squid -N
```

この手法（execute.sh経由）は以下の記事を参考にしています

https://zaki-hmkc.hatenablog.com/entry/2020/09/04/224822#%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8%E4%BD%9C%E6%88%90

# Build
```shell-session
$ sudo docker build -t alpine_squid:v1 ~/alpine_squid2/
[+] Building 1.5s (9/9) FINISHED
 => [internal] load build definition from Dockerfile                                                                                                    0.1s
 => => transferring dockerfile: 282B                                                                                                                    0.0s
 => [internal] load .dockerignore                                                                                                                       0.1s
 => => transferring context: 2B                                                                                                                         0.0s
 => [internal] load metadata for docker.io/library/alpine:3.17                                                                                          1.3s
 => [1/4] FROM docker.io/library/alpine:3.17@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126                                    0.0s
 => [internal] load build context                                                                                                                       0.1s
 => => transferring context: 271B                                                                                                                       0.0s
 => CACHED [2/4] RUN apk add --no-cache squid &&     rm -rf /etc/squid/squid.conf                                                                       0.0s
 => CACHED [3/4] COPY ./conf/dev_squid.conf /etc/squid/squid.conf                                                                                       0.0s
 => CACHED [4/4] COPY execute.sh /execute.sh                                                                                                            0.0s
 => exporting to image                                                                                                                                  0.0s
 => => exporting layers                                                                                                                                 0.0s
 => => writing image sha256:ea5946c33913306679a8ca90cfae87e52e15976a775e7af1ff548888c87b54e1                                                            0.0s
 => => naming to docker.io/library/alpine_squid:v1
```

# RUN
```shell-session
$ sudo docker image ls
REPOSITORY     TAG       IMAGE ID       CREATED          SIZE
alpine_squid   v1        ea5946c33913   17 minutes ago   16.9MB

$ sudo docker run --name alpine_squid -d --rm -p 8080:8080 -p 8083:8083 alpine_squid:v1
eeaaf9931c963e46067d7503efcc6e749c95adfd9d1ee0ad00ead7cb0776c02b

$ sudo docker ps -a
CONTAINER ID   IMAGE             COMMAND         CREATED         STATUS         PORTS                                                                                  NAMES
eeaaf9931c96   alpine_squid:v1   "/execute.sh"   4 seconds ago   Up 3 seconds   0.0.0.0:8080->8080/tcp, :::8080->8080/tcp, 0.0.0.0:8083->8083/tcp, :::8083->8083/tcp   alpine_squid
```

# Squid
* squid -v による configure option表示
* --enable-ssl-crtd と --with-openssl が確認できるため、目的の SSL Bump ReadyのSquidとなっている（ハズ） 
```shell-session
$ sudo docker exec alpine_squid squid -v |sed "s/' '/\n/g"
Squid Cache: Version 5.7
Service Name: squid

This binary uses OpenSSL 3.0.8 7 Feb 2023. configure options:  '--build=x86_64-alpine-linux-musl
--host=x86_64-alpine-linux-musl
--prefix=/usr
--datadir=/usr/share/squid
--sysconfdir=/etc/squid
--libexecdir=/usr/lib/squid
--localstatedir=/var
--with-logdir=/var/log/squid
--disable-strict-error-checking
--disable-arch-native
--enable-removal-policies=lru,heap
--enable-auth-digest
--enable-auth-basic=getpwnam,NCSA,SMB,SMB_LM,RADIUS
--enable-epoll
--enable-external-acl-helpers=file_userip,unix_group,wbinfo_group
--enable-auth-ntlm=fake,SMB_LM
--enable-auth-negotiate=kerberos,wrapper
--disable-mit
--enable-heimdal
--enable-delay-pools
--enable-openssl
--enable-ssl-crtd
--enable-linux-netfilter
--enable-ident-lookups
--enable-useragent-log
--enable-cache-digests
--enable-referer-log
--enable-async-io
--enable-truncate
--enable-arp-acl
--enable-htcp
--enable-carp
--enable-poll
--enable-follow-x-forwarded-for
--with-large-files
--with-default-user=squid
--with-openssl
build_alias=x86_64-alpine-linux-musl
host_alias=x86_64-alpine-linux-musl
CC=gcc
CFLAGS=-Os -fomit-frame-pointer
CPPFLAGS=-Os -fomit-frame-pointer
CXX=g++
CXXFLAGS=-Os -fomit-frame-pointer
BUILDCXX=g++
BUILDCXXFLAGS=-Os -fomit-frame-pointer'
```

# 最後に
* 残課題のまとめ
    1. パッケージインストールとconf,execute.sh配置でビルドステージを分ける「マルチステージビルド」に挑戦したがうまくいかず
    1. dockerfileを開発/検証/本番環境でどう管理するか
    1. Firewall設定はどこで書くのがセオリーなのか。このままでは丸裸なので
    1. rootlessとすべきか？今回のコンテナ自体はroot起動だがsquidはsquidユーザーで呼んでいる。コンテナへ侵入されたらホストへ波及するので、基本はrootlessとすべきでしかない？