Skaffold: How to exclude files from being rebuilt?

Created on 9 Mar 2019  路  22Comments  路  Source: GoogleContainerTools/skaffold

Expected behavior

I want to disable rebuild behavior for typescript (.ts) files.
I want it to watch only .js files do hot reload and ignore .ts files

Actual behavior

Currently whenever I make any change in typescript, then it rebuilds the whole docker image.
Without typescript, live reload for .js files work very well. But with typescript it rebuild everytime that takes a lot of time.

Information

  • Skaffold version: version 0.23.0
  • Operating system: Debian
  • Contents of skaffold.yaml:
apiVersion: skaffold/v1beta5
kind: Config
build:
  artifacts:
    - image: credisales/gateway_svc
      context: api-gateway-svc
      sync:
        "**/*.js": "dist/"

deploy:
  kubectl:
    manifests:
      - "**/k8s"

Steps to reproduce the behavior

  1. just try to type and save in typescript file and it would start rebuild.

I really like this tool and I love to continue my adventures with skaffold. But I really need some solution for this issue.
Please let me know if there is any solution for this.
Thanks in advance.

aresync kinquestion

Most helpful comment

this will actually require that we add a sync "blacklist" to the config.

sync:
  includes:
    "**/*": "dist/"
  excludes:
    "**/*.ts"

we've been debating whether or not it makes sense to allow syncing **/* though, since this could potentially allow users to accidentally sync source files and bypass the watcher. we'll also need to figure out how this will interact with inferring sync maps from the dockerfile, if we go that route.

All 22 comments

Thanks for filing the issue @ayyazzafar!
Can you share your Dockerfile as well for better understanding?
Do I understand correctly that TS files are COPY-d into the Docker image, they are transpiled to Javascript files?
It seems like you want to disable rebuilding for TS files, right?
One workaround could be to actually add TS files to the sync group, have you tried that?

Thanks for filing the issue @ayyazzafar!
Can you share your Dockerfile as well for better understanding?
Do I understand correctly that TS files are COPY-d into the Docker image, they are transpiled to Javascript files?
It seems like you want to disable rebuilding for TS files, right?
One workaround could be to actually add TS files to the sync group, have you tried that?

Hello @balopat !
Thank you so much for quick response.
Here is my Docker code:

FROM node:8.15.0-jessie ENV PORT=8080 EXPOSE 8080 COPY . . RUN npm install RUN npm run build CMD [ "npm", "run", "watch-node" ]
Yes you are right. I copy TS files into Docker image and then transpile it to javascript files.
Yes I want to disable rebuilding for TS files.
And no I did not try sync group. How can I add files to sync group?

@balopat I would be really thankful for you to answer my above questions.

Hey @ayyazzafar , you can add files to the sync group by making this change to your skaffold.yaml:

apiVersion: skaffold/v1beta5
kind: Config
build:
  artifacts:
    - image: credisales/gateway_svc
      context: api-gateway-svc
      sync:
        "**/*.js": "dist/"
        "**/*.ts": "<destination>"

this will actually require that we add a sync "blacklist" to the config.

sync:
  includes:
    "**/*": "dist/"
  excludes:
    "**/*.ts"

we've been debating whether or not it makes sense to allow syncing **/* though, since this could potentially allow users to accidentally sync source files and bypass the watcher. we'll also need to figure out how this will interact with inferring sync maps from the dockerfile, if we go that route.

@nkubala Bypassing the watcher should not happen with the current implementation. The sync map pattern is only matched against events coming from the watcher. However, excludes is a good point. I think I'll add this as an open question to the sync design proposal.
Update: see #1844

@nkubala - well - in the workaround I was suggesting, I was using the sync group as a blacklist for rebuild!! :) it is a bit of a hack as you technically don't need the TS files in the container, but it can stop from rebuilding. If you add JS files to sync too - it will hot sync both.

I changed the title as it was misleading and clarified the description as well.

I have one case where the blacklist would be really useful.
I have a php project, with composer and vendor.
I have my vendor locally, and copy them into my container with the Dockerfile.
Of course the vendor may change in the container, then I want to retrieve those changes, kubectl cp, but then the vendor copied locally will trigger the watcher, and it will sync back into the container those vendor (could be about 20k files), which is not necessary.
So yeah, I would love to see such kind of feature! :)

@igoooor Can you explain how your project folder is structured? At the moment, you can only define inclusion rules, e.g.

sync:
  infer:
  - src/**.php

If your vendor folder is on the root level, this could already work.

@corneliusweig If I follow the inclusion rule you defined, and manage to exclude the vendor folder this way, then a change in the vendor would then rebuild the whole container, which is also not I want to achieve.
I would like my vendor folder to be copied into my docker container, but not sync, and without rebuild.
For example:

Project structure:

- ./project/
- ./project/src/
- ./project/vendor/

Dockerfile:

FROM php
COPY ./project/ /app

Now if I do that:
skaffold.yaml:

sync:
  infer:
  - src/**.php

Then a change in the vendor folder would trigger a docker image rebuild

And if I do that:
skaffold.yaml:

sync:
  infer:
  - **

Then a change in the vendor folder would sync into the container

And I want to avoid both scenarios

@igoooor I'm a bit puzzled here. You don't want a rebuild, but also no sync (aka copy). So how should the container be updated?

You got it, it should not update, that鈥檚 why I want to completely ignore it, even though they are copied by the Dockerfile

Any update on this topic ? Because I have a similar use case :

I'am using NestJS, that is a microservice oriented framework for NodeJS which uses Typescript.
I'd like to use skaffold during the development phase to deploy my microservices on my K8S cluster and sync my code with my pods.

I have a multi-stage build Dockerfile that transpiles typescript to javascript.

What I need is that skaffold just watches my local /dist/src/*.js and sync them in my pods without rebuilding the whole thing each time I save a .ts file.

To sum up, I launch a skaffold dev command that build & deploy my service. Then, if I add some code in any ts file and save it, nothing happens. But if I launch a tsc command to transpile my TS files, that will regenerate all my /dist/src/*.js and trigger the skaffold sync.

Thank you for your great job!

@cabrinoob I think Skaffold behaves as expected in your case. You simply have to adapt your setup. Basically, you have two options:

  1. Build the .js files from the .ts files outside the container and sync the .js files into the conainer (this is what you described). For that, you should consider something like tsc-watch.
  2. Sync the .ts files into the container and run a development toolchain inside which transpiles the .ts to .js. Or you simply run nodemon inside the container in typescript mode (see https://stackoverflow.com/questions/37979489/how-to-watch-and-reload-ts-node-when-typescript-files-change).

Maybe you can also take some inspiration from https://github.com/corneliusweig/skaffold-create-react-app.

@corneliusweig : It is exactly the first option I want, but it does not work as I expect :

1- First, I launch skaffold dev with this config :

apiVersion: skaffold/v2alpha1
kind: Config
metadata:
  name: hello-world
build:
  artifacts:
  - image: xxxxx/hello-world
    context: .
    sync:
      infer:
      - '**/*.js'
deploy:
  kubectl:
    manifests:
    - k8s/*.yaml

As you can see, I'd like to synchronize only *.js files.
At this moment, my pod is running on my K8S cluster and my terminal shows watching for changes

2- Then I modify something in my *.ts files, but right after I save a ts file, skaffold triggers a complete rebuild of my docker image.

It seems that skaffold is watching changes over all the project files, not only those you want to sync.

@cabrinoob Can you make sure that your Dockerfile only copies .js files and no .ts files? For example, COPY * ./ would usually also copy any .ts files. Then Skaffold behaves as expected, because a container input file has changed which is not sync'able.

@corneliusweig : I'am using a multistage build image. On the first stage I copy all ts files that I build, and in the second stage I copy the build artifact of the fist stage (/dist/src/*.js files) in the final stage.

So I don't know exactly if skaffold is aware of this multistage build dockerfile type ...

@cabrinoob Ok, that explains it. This setup is simply not supported by sync.

Think of it this way: sync is a shortcut to skip rebuilding containers. However, if the input to your final container comes from the first build stage, this is not possible.
In general, sync only considers the final stage of a docker build, and the input files must come from the host filesystem.

Sounds like this has been answered.

@cabrinoob Ok, that explains it. This setup is simply not supported by sync.

Think of it this way: sync is a shortcut to skip rebuilding containers. However, if the input to your final container comes from the first build stage, this is not possible.
In general, sync only considers the final stage of a docker build, and the input files must come from the host filesystem.

It may not support now (1.8) but it used to (1.0) because I was away from backend for a while, and when came back I updated skaffold and now the setup that allowed me to develop 5+ services does not work anymore. The setup was similar to the one from cabrinoob (nodejs, typescript, lerna). I had dockerfiles for each service that in first stage copied ts, transpiled to js and send to second and last stage where only js files were used. For dev purposes nodemon, watched for changes to js files and restarted the app. When working on a given service I run tsc -w and let skaffold synch /dist/**.js to container. This allowed to have one dockerfile for dev and prod (except for nodemon).

Given that multistage images are helpful to speedup the CI/CD pipelines, having 2 completely different dockerfiles for dev and prod would probably affect the goal to develop on same env as production...

EDIT: what i forgot to mention is that im using skaffold together with cloudecode for vscode. Oddly enough, same skaffold.yml works as I expect when i launch it via the [Deprecated] Deploy Application Continuosly while it works how @corneliusweig expects when I launch it via Run On Kubernetes.

Still, the skaffold beahaviour does not look very consistent, but maybe I just have to look to the other project.

I'm in a hurry with deadlines now, but I will probably have a look to how skaffold is triggered in the two different cases.

I would also like to disable rebuilding the image during dev. I have a setup where the frontend is Angular and is working great with the sync feature.

But the backend is a database. I use skaffold to build the images for the database as well as deploying them on Kubernetes. The database has source code as well that is added to the Dockerfile during build. During development, I am using VSCode which happens to have a plugin for this database that synchs the code automatically for me and allows me to debug it as well (much more than file synching). But every time I save a change, skaffold will rebuild the image.

I would like to continue to be able to build this image during "skaffold build", but ignore watching for files during "skaffold dev". If I don't specify sync, skaffold will always rebuild. If I specify it, skaffold will also rebuild. I tried to tell it to just watch for a file that I never touch but it will also rebuild the image if I touch the other files.

In my case all I need is to completely disable source code watching for a single image during the "dev" profile.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

abatilo picture abatilo  路  4Comments

gbird3 picture gbird3  路  3Comments

kdevu picture kdevu  路  3Comments

heroic picture heroic  路  4Comments

Morriz picture Morriz  路  3Comments