5

Let's say I want to use Docker for an app, which consists of two parts. These parts are different, but they have some shared libraries.

So, I have two folders:

part1/
    Dockerfile
    src/
part2/
    Dockerfile
    src/

However, I want them to share some files (e.g., libraries), because DRY. Unfortunately there doesn't seem to be any good directory structure which would allow me to do that: Dockerfiles can't refer to the parent folders, and I can't put them both in the top folder because I'm not allowed to change the name of the Dockerfile.

Some of these files are required at the building step, so I can't use the "bind mount a volume" option of docker run - docker run is too late.

I see these options, and I don't like them:

  1. I can add a folder named shared/, and use a hack to put it "into" both of my app folders. These hacks include mounting it somehow (which is annoying, would require me to do it every time, and inexplicable to my co-workers whom I'm trying to sell Docker) or copying it before building (doable if I hide building into a build-script, copy the folder before the build and remove it just after; however, it invalidates the build cache even if the shared folder is not changed, and prone to bugs)

  2. I can split the project into 3 different projects and link them together using git-sub-something. This configuration is very hard to work with (or I don't know how to do that).

I assume my situation is not that uncommon, especially with the motto "decouple applications into multiple containers". So probably there are very nice ways to work with that. Any clues?

valya
  • 938

1 Answers1

0

I know it's a bit late, but being faustrated by the same issue, I've ended up writing my own framework for generating Dockerfiles.

It's called Sand and you can find it here

It allows you to share code between Sandfiles, which are later being converted into Dockerfiles

Given the following directory structure:

my-monorepo/
│
├── tweet-service/
|   ├── src/
|   ├── ...
│   └── Sandfile
│
├── home-timeline/
|   ├── src/
|   ├── ...
│   └── Sandfile
│
└── Sandfile

You can write your Sandfiles like this:

# ./my-monorepo/Sandfile
from sand import *

def MyService(name): From("ubuntu", "20.04") Run("apt-get install python3") Copy(Src="src", Dst="/app") Entrypoint(f"python3 /app/{name}.py")

Sand("tweet-service") Sand("home-timeline")

# ./my-monorepo/tweet-service/Sandfile
from sand import *

MyService("tweet-service") # Defined in ../Sandfile
# ./my-monorepo/home-timeline/Sandfile
from sand import *

MyService("home-timeline") # Defined in ../Sandfile
gkpln3
  • 169
  • 1
  • 2