Reloading Go apps automatically while developing

There are some ways to automatically reload Go apps while developing, to not have to manually stop your app, build it, run it. Recently I ran into this article about a nice tool called Fresh.

I wanted to start using live reload (or hot reload) for a project of mine, but it had a particularity which gave me troubles when I tried Fresh. My case was:

  • I had a multiple apps Git repository
  • The apps were sharing some packages
  • If I edited app1 and the packages it used, I didn’t want both app1 and app2 to be restarted, only app1 (similar for app2)

The repository’s structure:

  • /apps
    • app1
    • app2
  • /packages
    • chronos
    • random

So I made an update for Fresh to support directory watch for other directories than the app’s. And I’ve sent a pull request to the original repository. But I wanted to go with this faster, and searched for other solutions. And I’ve found fswatch.

I wanted to have everything in Docker containers. This is my Dockerfile:

FROM golang:1.10-alpine3.7

RUN apk add --update --no-cache git && \
    mkdir -p $GOPATH/bin && \
    go get github.com/codeskyblue/fswatch

ARG APP

WORKDIR /go/src/github.com/andreiavrammsd/go-live-reload/apps/${APP}

COPY ./.fsw.yml /.fsw.yml
RUN sed -i "s/<app>/${APP}/g" /.fsw.yml

CMD fswatch -config /.fsw.yml

The config file “.fsw.yml for fswatch had some important properties:

  • cmd: the command to execute after files changes
  • watch_paths: the paths to watch for changes
desc: <app>
triggers:
- name: ""
  pattens:
  - '**/*.*'
  env:
    DEBUG: "1"
  cmd: cd /go/src/github.com/andreiavrammsd/go-live-reload/apps/<app> && go get -t && go vet -composites=false && go build -o /bin/<app> && /bin/<app>
  shell: true
  delay: 100ms
  stop_timeout: 500ms
  signal: KILL
  kill_signal: ""
watch_paths:
- /go/src/github.com/andreiavrammsd/go-live-reload/apps/<app>
- /go/src/github.com/andreiavrammsd/go-live-reload/packages
watch_depth: 1

You can see the <app> placeholder which is replaced with the app’s directory name in the Dockerfile. The app’s directory is sent as build argument in the docker compose file.

version: '3'

services:
  app1:
    build:
      context: .
      args:
        APP: app1
    volumes:
      - ../:/go/src/github.com/andreiavrammsd/go-live-reload
    restart: unless-stopped
  app2:
    build:
      context: .
      args:
        APP: app2
    volumes:
      - ../:/go/src/github.com/andreiavrammsd/go-live-reload
    restart: unless-stopped

I just started the apps:

docker-compose up -d

And then I watched the apps logs to see how each app was restarted after its code had changed:

docker-compose logs -f

Get the full Go live reload source code on GitHub.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.