【2024年10月版】Ubuntu22.04 で Docker + Samba で Windowsとファイル共有、サービス化

# はじめに

Ubuntu側でファイル共有サーバを作りたいな。。。

そうだ、Samba しよう

環境汚したくないし、Dockerでやろ

:::note info
2024年10月に再構築する機会があったので更新しました。
:::

# 前提条件

- 環境

```terminal
$ uname -a
Linux smb_host 6.5.0-41-generic #41~22.04.2-Ubuntu SMP PREEMPT_DYNAMIC Mon Jun  3 11:32:55 UTC 2 x86_64 x86_64 x86_64 GNU/Linuxx86_64 x86_64 GNU/Linux
$ cat /etc/os-release
PRETTY_NAME="Ubuntu 22.04.5 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.5 LTS (Jammy Jellyfish)"
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=jammy
```

- 共有するフォルダ
  `/export/smb_share`

- UbuntuのサーバのIPアドレスは、`192.168.100.100`
- Dockerはインストール済み
```terminal
$ docker -v
Docker version 27.3.1, build ce12230
```
- Docker未インストールなら、[【2024年08月版】Ubuntu への Docker / DockerCompose インストールメモ](https://qiita.com/nouernet/items/7dfb11cd8c3c929821b1) を参照
- まずはguestアクセスでの共有を作成し、必要ならアクセス権を設定する

# 設定

## フォルダの権限を調整（必要なら）

```
$ sudo chown -R nobody:nogroup /export/smb_share
$ sudo chmod -R 777 /export/smb_share 
```

## docker-compose.yml の入手

```terminal
$ curl -O https://raw.githubusercontent.com/ServerContainers/samba/master/docker-compose.yml
```
## docker-compose.yml の編集
- ユーザに関する記述を削除、共有の記述を削除して、今回共有する `shared` について記述
```terminal
$ cp docker-compose.yml docker-compose.yml.back
$ vim docker-compose.yml
$ diff docker-compose.yml.back docker-compose.yml
diff --git a/docker-compose.yml.back b/docker-compose.yml
index 0688958..1a59100 100644
--- a/docker-compose.yml.back
+++ b/docker-compose.yml
@@ -23,40 +23,42 @@ services:
       #WSDD2_DISABLE: 1
       #AVAHI_DISABLE: 1
 
-      GROUP_family: 1500
-
-      ACCOUNT_alice: alipass
-      UID_alice: 1000
-      GROUPS_alice: family
-
-      ACCOUNT_bob: bobpass
-      UID_bob: 1001
-      GROUPS_bob: family
-
-      # example for hashed password (user: foo | password: bar) - generated using create-hash.sh script.
-      ACCOUNT_foo: "foo:1000:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:86C156FC198B358CCCF6278D8BD49B6A:[U          ]:LCT-61B0859A:"
-      UID_foo: 1002
-      GROUPS_foo: family
-
-      SAMBA_VOLUME_CONFIG_shared_home: "[Home]; path=/shares/homes/%U; valid users = alice, bob, foo; guest ok = no; read only = no; browseable = yes"
-
-      SAMBA_VOLUME_CONFIG_aliceonly: "[Alice Share]; path=/shares/alice; valid users = alice; guest ok = no; read only = no; browseable = yes"
-      SAMBA_VOLUME_CONFIG_alicehidden: "[Alice Hidden Share]; path=/shares/alice-hidden; valid users = alice; guest ok = no; read only = no; browseable = no"
-
-      SAMBA_VOLUME_CONFIG_bobonly: "[Bob Share]; path=/shares/bob; valid users = bob; guest ok = no; read only = no; browseable = yes"
-      
-      SAMBA_VOLUME_CONFIG_public: "[Public]; path=/shares/public; valid users = alice, bob, foo; guest ok = no; read only = no; browseable = yes; force group = family"
-      SAMBA_VOLUME_CONFIG_public_ro: "[Public ReadOnly]; path=/shares/public; guest ok = yes; read only = yes; browseable = yes; force group = family"
-      
-      SAMBA_VOLUME_CONFIG_timemachine: "[TimeMachine]; path=/shares/timemachine/%U; valid users = alice, bob, foo; guest ok = no; read only = no; browseable = yes; fruit:time machine = yes; fruit:time machine max size = 500G"
+# comment out
+#      GROUP_family: 1500
+#
+#      ACCOUNT_alice: alipass
+#      UID_alice: 1000
+#      GROUPS_alice: family
+#
+#      ACCOUNT_bob: bobpass
+#      UID_bob: 1001
+#      GROUPS_bob: family
+#
+#      # example for hashed password (user: foo | password: bar) - generated using create-hash.sh script.
+#      ACCOUNT_foo: "foo:1000:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:86C156FC198B358CCCF6278D8BD49B6A:[U          ]:LCT-61B0859A:"
+#      UID_foo: 1002
+#      GROUPS_foo: family
+#
+#      SAMBA_VOLUME_CONFIG_shared_home: "[Home]; path=/shares/homes/%U; valid users = alice, bob, foo; guest ok = no; read only = no; browseable = yes"
+#
+#      SAMBA_VOLUME_CONFIG_aliceonly: "[Alice Share]; path=/shares/alice; valid users = alice; guest ok = no; read only = no; browseable = yes"
+#      SAMBA_VOLUME_CONFIG_alicehidden: "[Alice Hidden Share]; path=/shares/alice-hidden; valid users = alice; guest ok = no; read only = no; browseable = no"
+#
+#      SAMBA_VOLUME_CONFIG_bobonly: "[Bob Share]; path=/shares/bob; valid users = bob; guest ok = no; read only = no; browseable = yes"
+#      
+#      SAMBA_VOLUME_CONFIG_public: "[Public]; path=/shares/public; valid users = alice, bob, foo; guest ok = no; read only = no; browseable = yes; force group = family"
+#      SAMBA_VOLUME_CONFIG_public_ro: "[Public ReadOnly]; path=/shares/public; guest ok = yes; read only = yes; browseable = yes; force group = family"
+#      
+#      SAMBA_VOLUME_CONFIG_timemachine: "[TimeMachine]; path=/shares/timemachine/%U; valid users = alice, bob, foo; guest ok = no; read only = no; browseable = yes; fruit:time machine = yes; fruit:time machine max size = 500G"
+      
+# append share config
+      SAMBA_VOLUME_CONFIG_share: "[shared]; comment = ubuntu22.04 share; path=/shared; available = yes; read only = no; browsable = yes; public = yes; writeable = yes; guest ok = yes"
     volumes:
       - /etc/avahi/services/:/external/avahi
       
       # avoid loops when mounting folders to /shares (I'd recommend explicit mapping for each share)
-      - ./shares/alice:/shares/alice
-      - ./shares/alice-hidden:/shares/alice-hidden
-      - ./shares/bob:/shares/bob
-      - ./shares/public:/shares/public
-      - ./shares/homes:/shares/homes
-      - ./shares/timemachine:/shares/timemachine
+# comment out
+#      - ./shares/alice:/shares/alice
+#      - ./shares/alice-hidden:/shares/alice-hidden
+#      - ./shares/bob:/shares/bob
+#      - ./shares/public:/shares/public
+#      - ./shares/homes:/shares/homes
+#      - ./shares/timemachine:/shares/timemachine
+# append share config
+      - /export/smb_share:/shared
```

# 起動

```terminal
$ docker compose up -d
[+] Building 0.0s (0/0)
[+] Running 1/1
 ✔ Container docker_smb-samba-1  Started
```

- ログを確認
```terminal
$ docker compose logs -f
```

# 動作確認

Windows端末から、`//192.168.100.100/shared` で共有を開く

# サービス化

## 稼働中の docker compose を停止

```terminal
$ docker compose down
```

## docker-compose.yml の配置

- `/usr/local/bin/docker_smb` に配置する
- `docker_smb` は適当に替えても良い、サービス名になる

```terminal
$ sudo mkdir /usr/local/bin/docker_smb
$ sudo cp docker-compose.yml /usr/local/bin/docker_smb/
```

## systemd のユニットファイルを作成

- ユニットファイル ```/etc/systemd/system/docker-compose-service@.service``` を作成する

```terminal
$ cat /etc/systemd/system/docker-compose-service@.service 
[Unit]
Description=%i managed by docker-compose
Requires=docker.service

[Service]
Type=simple

Environment=COMPOSE_FILE=/usr/local/bin/%i/docker-compose.yml

ExecStartPre=-/usr/bin/docker compose -f ${COMPOSE_FILE} down --volumes
ExecStart=/usr/bin/docker compose -f ${COMPOSE_FILE} up
ExecStop=/usr/bin/docker compose -f ${COMPOSE_FILE} down --volumes 

[Install]
WantedBy=multi-user.target
```

## ユニットファイルの読み込み

- ユニットファイルを編集したときも再読み込みが必要

```terminal
$ sudo systemctl daemon-reload
```

## systemd のサービス登録と起動

```terminal
$ sudo systemctl enable --now docker-compose-service@docker_smb
```

## systemd でサービス化した samba の動作確認

```terminal
$ sudo systemctl status docker-compose-service@docker_smb
```

または

```terminal
$ docker-compose logs -f
```

# 設定（アクセス権を追加）

## フォルダの権限を調整（必要なら）

```
$ sudo chmod -R 775 /export/smb_share 
```

## パスワードハッシュの取得

docker-compose.ymlに記載するハッシュを取得
```
docker run -ti --rm --entrypoint create-hash.sh ghcr.io/servercontainers/samba
>> Enter username: dev
>> New password: 
>> Retype password: 
dev:1000:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:0DF5244B85806F3154907A58D7765F91:[U          ]:LCT-67138B0B:
```

## docker-compose.yml の編集
- ユーザに関する記述を追加、共有の記述を編集
```
+      ACCOUNT_dev: "dev:1000:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:0DF5244B85806F3154907A58D7765F91:[U          ]:LCT-67138B0B"
-      SAMBA_VOLUME_CONFIG_share: "[shared]; comment = ubuntu share; path=/shared; available = yes; read only = no; browsable = yes; public = yes; writeable = yes; guest ok = yes"
+      SAMBA_VOLUME_CONFIG_share: "[shared]; comment = ubuntu share; path=/shared; available = yes; read only = no; browsable = yes; public = no;  writeable = yes; guest ok = no; valid users = dev"
```

## systemd の再起動

```terminal
$ sudo systemctl restart docker-compose-service@docker_smb
```

# さいごに

かんたんでしたね

# 参考資料

[samba - (ghcr.io/servercontainers/samba) [x86 + arm]](https://github.com/ServerContainers/samba)
[GitHub - ServerContainers - samba](https://github.com/ServerContainers/samba)