5

What I have

I have 2 python apps that share a few bits of code, enough that I am trying to isolate the shared parts into modules/packages/libraries (I'm keeping the term vague on purpose, as I am not sure what the solution is). All my code is in a monorepo, because I am hoping to overcome some of the annoyances of managing more repos than we have team members.

Currently my file layout looks like:

+ myproject
  + appA
  | + python backend A
  | + js frontend
  + appB
  | + B stuff
  + libs
    + lib1
    + lib2

Both appA and appB use lib1 and lib2 (they are essentially data models to abstract away the shared database). appA is a webapp with several components, not all of which are python. It is deployed as a docker stack that involve a bunch of containers. I manage my dependencies with poetry to ensure reproducible builds, etc... Each python component (appA, appB...) have their own pyproject.toml file, virtual env, etc...

appB is deployed separately.

All development is on linux, if it makes any difference.

What I need

I am looking for a clean way to deal with the libs:

  • development for appA is done in a local docker-compose setup. The backend auto-reloads on file changes (using a docker volume), and I would like it to happen for changes in the libs too.
  • development for appB is simpler, but is moving to docker so the problem will be the same.

What I've tried

  • My initial "solution" was to copy the libs folder over to a temporary location for development in appA. It works for imports, but it's messy as soon as I want to change the libs code (which is still quite often), as I need to change the original file, copy over, rebuild the container.
  • I tried symlinking the libs into the backend's docker environment, but symlinks don't seem to work well with docker (it did not seem to follow the link, so the files don't end up in the docker image, unless I essentially copy the files inside the docker build context, which defeats the purpose of the link.)
  • I have tried packaging each lib into a python package, and install them via poetry add ../../libs/lib1 which doesn't really work inside docker because the paths don't match, and then I'm back to the symlink issue.

I am sure there is a clean way to do this, but I can't figure it out. I know I could break up the repo into smaller ones and install dependencies, but development would still cause problems inside docker, as I would still need to rebuild the container each time I change the lib files, so I would rather keep the monorepo.

Laurent S
  • 4,106
  • 3
  • 26
  • 50
  • 1
    If you are using docker-compose anyway you could use volumes to mount the local libs in your container and be able to edit them in your host system and the container. Not super fancy, but that should work, right? – ckaserer Feb 25 '20 at 19:07
  • Currently I have a volume like `path/to/appA_source:/app` so you're saying I could add something like `libs/lib1:/libs_in_container/lib1`? If I do that, what happens for actual deployment? Do I just copy the files over then? – Laurent S Feb 25 '20 at 19:15
  • 1
    Well, how would you do deployment for the appA? you would not use the volume mount for actual deployments to production, hence you could build the image with the app and libs and only on your workstation overwrite the data via volume mounts – ckaserer Feb 26 '20 at 09:48
  • @ckaserer your suggestion seems to work, indeed. In short, in the docker files I do `COPY ../libs/lib1 /app/lib1` and then for local development, I mount `../libs/lib1` onto `/app/lib1`. That gives me the behaviour I was looking for. I use a split docker-compose file for this. The setup causes a few issues with various tools needing some extra config so they know that the libs are part of the code base, but nothing impossible. Thanks for the idea! – Laurent S Feb 26 '20 at 18:24

1 Answers1

1

If you are using docker-compose anyway you could use volumes to mount the local libs in your container and be able to edit them in your host system and the container. Not super fancy, but that should work, right?

@ckaserer your suggestion seems to work, indeed. In short, in the docker files I do COPY ../libs/lib1 /app/lib1 and then for local development, I mount ../libs/lib1 onto /app/lib1. That gives me the behavior I was looking for. I use a split docker-compose file for this. The setup causes a few issues with various tools needing some extra config so they know that the libs are part of the code base, but nothing impossible. Thanks for the idea!

So even though it's not an ideal solution locally mounting over the app and lib directories works on Linux systems.

FYI: On Windows hosts you might run into trouble if you want to watch for file changes as that is not propagated from a windows host to a Linux container.

ckaserer
  • 4,827
  • 3
  • 18
  • 33