Skaffold File Syncを試す

Skaffoldをこよなく愛する貴殿におかれましては、`$ skaffold dev -f ./xxxx.yaml` とかしてファイルに変更があったらリビルドされて開発しているかと思います。
Buildkitとかがあるにせよ、まいどまいどリビルドされていては堪忍ならん、これではdocker-composeでボリュームマウントのほうがよいではないか！？と常日頃からイライラしていませんか。

Skaffold様にはファイルの変更があった際にコピーだけしてくれる便利な機能があるようで、その名をFile Syncというようです。(そのまんまやんけ)

結局のところ、[File Sync  beta](https://skaffold.dev/docs/pipeline-stages/filesync/) で [SkaffoldのFile sync機能を使えばイメージのビルドなしにコンテナに反映できて捗る](https://qiita.com/sheepland/items/a0523d20863a246fd260) ってことなのですが、こちらの機能を試してみました。


# TL;DR

適当なファイルを作ってSkaffoldのinfer sync設定を試しています。

```
$ skaffold version
v1.7.0
```


# ファイル配置


こんな感じでファイルを配置しました。jsファイルはconsole.log()で適当につぶやいているだけです。`skaffold.dev.yaml` を編集してファイルがsyncされるかどうかを試してみます。



```
─murata@deroris ~/tmp/docker-reg-test
─$ tree .

── Dockerfile
── dir
   └── dir.text
── k8s.dev.yaml
── main.js
── skaffold.dev.yaml
── sub.js
```

Dockerがそのまま終わらないようにtailで止めています。

```:Dockerfile
FROM node:13

WORKDIR /usr/src/app
COPY . .

ENTRYPOINT tail -f /dev/null
```


```:k8s.dev.yaml
apiVersion: v1
kind: Pod
metadata:
  name: skaffold-file-sync
spec:
  containers:
    - name: skaffold-file-sync
      image: dev/skaffold-file-sync
```

```:skaffold.dev.yaml

apiVersion: skaffold/v1
kind: Config
build:
  artifacts:
  - image: dev/skaffold-file-sync
    context: ./
    docker:
      dockerfile: ./Dockerfile
  local:
    push: false
    useBuildkit: true
deploy:
  kubectl:
    manifests:
    - ./k8s.dev.yaml

```

```:main.js
console.log("main dayo");
```

```:sub.js
console.log("sub desu");
```

```:dir/dir.text
tadano text desu.
```


# リビルド時とFile Syncの挙動


## まずはいつも通り

このまま devしてみます。


```
╭─murata@deroris ~/tmp/docker-reg-test 
╰─$ skaffold dev -f ./skaffold.dev.yaml                                                                             
Listing files to watch...
 - dev/skaffold-file-sync
Generating tags...
 - dev/skaffold-file-sync -> WARN[0000] Unable to find git commit: running [git describe --tags --always]
 - stdout:
 - stderr: "fatal: Not a git repository (or any of the parent directories): .git\n": exit status 128
dev/skaffold-file-sync:dirty
Checking cache...
 - dev/skaffold-file-sync: Not found. Building
Building [dev/skaffold-file-sync]...
[+] Building 0.5s (8/8) FINISHED
 => [internal] load build definition from Dockerfile                                                                
 => => transferring dockerfile: 117B                                                                                
 => [internal] load .dockerignore                                                                                   
 => => transferring context: 2B                                                                                     
 => [internal] load metadata for docker.io/library/node:13                                                          
 => [1/3] FROM docker.io/library/node:13                                                                            
 => CACHED [2/3] WORKDIR /usr/src/app                                                                               
 => [internal] load build context                                                                                   
 => => transferring context: 900B                                                                                   
 => [3/3] COPY . .                                                                                                  
 => exporting to image                                                                                              
 => => exporting layers                                                                                             
 => => writing image sha256:83c31b6ecb5ac9b41f61bc8e8ce799c01ec591010a2b33dba37b45bfc99733a5                        
 => => naming to docker.io/dev/skaffold-file-sync:dirty                                                             
Tags used in deployment:
 - dev/skaffold-file-sync -> dev/skaffold-file-sync:83c31b6ecb5ac9b41f61bc8e8ce799c01ec591010a2b33dba37b45bfc99733a5
   local images can't be referenced by digest. They are tagged and referenced by a unique ID instead
Starting deploy...
 - pod/skaffold-file-sync created
Waiting for deployments to stabilize...
Deployments stabilized in 18.832686ms
Watching for changes...


```

main.jsを編集してみました。まぁ普通にDockerのリビルドが走ります。

```
Generating tags...
 - dev/skaffold-file-sync -> WARN[0035] Unable to find git commit: running [git describe --tags --always]
 - stdout:
 - stderr: "fatal: Not a git repository (or any of the parent directories): .git\n": exit status 128
dev/skaffold-file-sync:dirty
Checking cache...
 - dev/skaffold-file-sync: Not found. Building
Building [dev/skaffold-file-sync]...
[+] Building 0.4s (8/8) FINISHED
 => [internal] load build definition from Dockerfile                                                                
 => => transferring dockerfile: 37B                                                                                 
 => [internal] load .dockerignore                                                                                   
 => => transferring context: 2B                                                                                     
 => [internal] load metadata for docker.io/library/node:13                                                          
 => [1/3] FROM docker.io/library/node:13                                                                            
 => [internal] load build context                                                                                   
 => => transferring context: 274B                                                                                   
 => CACHED [2/3] WORKDIR /usr/src/app                                                                               
 => [3/3] COPY . .                                                                                                  
 => exporting to image                                                                                              
 => => exporting layers                                                                                             
 => => writing image sha256:0dbd605260be581cacbec04bebd9cb187141e9ca1d18879028238268a3a998b5                        
 => => naming to docker.io/dev/skaffold-file-sync:dirty                                                             
Tags used in deployment:
 - dev/skaffold-file-sync -> dev/skaffold-file-sync:0dbd605260be581cacbec04bebd9cb187141e9ca1d18879028238268a3a998b5
   local images can't be referenced by digest. They are tagged and referenced by a unique ID instead
Starting deploy...
 - pod/skaffold-file-sync configured
Waiting for deployments to stabilize...
Deployments stabilized in 1.902608ms
Watching for changes...

```


## main.jsをSyncFileに設定

これを追記します。

```
    sync:
      infer:
        - 'main.js'
```


```:skaffold.dev.yaml

apiVersion: skaffold/v1
kind: Config
build:
  artifacts:
  - image: dev/skaffold-file-sync
    context: ./
    docker:
      dockerfile: ./Dockerfile
    sync:
      infer:
        - 'main.js'
  local:
    push: false
    useBuildkit: true
deploy:
  kubectl:
    manifests:
    - ./k8s.dev.yaml

```

devします。

```
╭─murata@deroris ~/tmp/docker-reg-test 
╰─$ skaffold dev -f ./skaffold.dev.yaml
Listing files to watch...
 - dev/skaffold-file-sync
Generating tags...
 - dev/skaffold-file-sync -> WARN[0000] Unable to find git commit: running [git describe --tags --always]
 - stdout:
 - stderr: "fatal: Not a git repository (or any of the parent directories): .git\n": exit status 128
dev/skaffold-file-sync:dirty
Checking cache...
 - dev/skaffold-file-sync: Found Locally
Tags used in deployment:
 - dev/skaffold-file-sync -> dev/skaffold-file-sync:cec6fc645002bf59e5a21e3e92c178d08357e49dbf5deffe71f4112e48a1d8ad
   local images can't be referenced by digest. They are tagged and referenced by a unique ID instead
Starting deploy...
 - pod/skaffold-file-sync created
Waiting for deployments to stabilize...
Deployments stabilized in 18.831002ms
Watching for changes...
```

ここまでは同じですね。
main.jsを書き換えてみます。("main dayo2"に変えました。)


```
Syncing 1 files for dev/skaffold-file-sync:cec6fc645002bf59e5a21e3e92c178d08357e49dbf5deffe71f4112e48a1d8ad
Watching for changes...
```

2行が増えただけで、リビルドは走りませんでした。

コンテナの中を見てみます。

```
╭─murata@deroris ~/tmp/docker-reg-test 
╰─$ kubectl exec -it skaffold-file-sync cat main.js
console.log("main dayo2");
```

変わってますね。

ディレクトリ単位の場合には、infer:のところを下記のように書くようです。（サブディレクトリもすべてになる）
見たことある書式ですね。

```
    sync:
      infer:
        - 'dir/**/*'
```


じゃあ infer のところを`**/*`にしたら全部になるのか？


```
    sync:
      infer:
        - '**/*'
```


書き換えて実行してみました。

```
╭─murata@deroris ~/tmp/docker-reg-test 
╰─$ skaffold dev -f ./skaffold.dev.yaml                                                                             
Listing files to watch...
 - dev/skaffold-file-sync
Generating tags...
 - dev/skaffold-file-sync -> WARN[0000] Unable to find git commit: running [git describe --tags --always]
 - stdout:
 - stderr: "fatal: Not a git repository (or any of the parent directories): .git\n": exit status 128
dev/skaffold-file-sync:dirty

~~snip;

Watching for changes...



```

main.jsを書き換えてみます。(main dayo3に。

```
Syncing 1 files for dev/skaffold-file-sync:27fa6f319f7da2df2ecaa1eee671cbc0a85d4050c6e35e08884d08c08a8cb86b
Watching for changes...

```

いけました。

dir/dir.textもやってみます。(tadano text desu!!!!!!!!!!にしました。

```
Syncing 1 files for dev/skaffold-file-sync:27fa6f319f7da2df2ecaa1eee671cbc0a85d4050c6e35e08884d08c08a8cb86b
Watching for changes...
```

いけました。


# Dockerレジストリが別にある場合には？

Skaffold のlocal.pushをtrueにした場合にはどうなるのか試してみました。

```
  local:
    push: true
    useBuildkit: true
```

適当なGCRで試しました。

```
╭─murata@deroris ~/tmp/docker-reg-test 
╰─$ skaffold dev -f ./skaffold.dev.yaml
Listing files to watch...
 - gcr.io/docker-reg-test/ska-test
Generating tags...
 - gcr.io/docker-reg-test/ska-test -> WARN[0000] Unable to find git commit: running [git describe --tags --always]
 - stdout:
 - stderr: "fatal: Not a git repository (or any of the parent directories): .git\n": exit status 128
gcr.io/docker-reg-test/ska-test:dirty
Checking cache...
 - gcr.io/docker-reg-test/ska-test: Not found. Building
Building [gcr.io/docker-reg-test/ska-test]...
[+] Building 0.2s (8/8) FINISHED
 => [internal] load build definition from Dockerfile                                                                                               
 => => transferring dockerfile: 37B                                                                                                                
 => [internal] load .dockerignore                                                                                                                  

~~ snip;;


Deployments stabilized in 17.068646ms
Watching for changes...
Syncing 1 files for gcr.io/docker-reg-test/ska-test:dirty@sha256:2cb472bf2247dbd9245fc4726d773c83893cc1b117db64ad30c3e177b26345f1
Watching for changes...

```

おっ。ちゃんと動きました。

# まとめ

今まではローカルにnodejsやgolangを入れて、ある程度作ってからDockerImageにしていましたが、この方法なら最初からDockerImageで作れて環境の構築が楽そうです。

`ng serve`や golangのrealizeなどと組み合わせると捗るんじゃないでしょうか。

基本は `**/*` でよいのでは？と思っています。
ちなみにファイル削除の場合にはDockerImageからのリビルドになってしまうとのことです。inferのところはある程度絞ったほうがよさそうですね。

※ `skaffold run`の場合にはできません。

参考: 
- [File Sync  beta](https://skaffold.dev/docs/pipeline-stages/filesync/) 
- [SkaffoldのFile sync機能を使えばイメージのビルドなしにコンテナに反映できて捗る](https://qiita.com/sheepland/items/a0523d20863a246fd260)