I'm building two microservices and dockerizing them. I have a folder that contains a script (PackageA
) which I need in both services (ServiceA & B
). My folder structure is as following:
Root
|
|--Docker
|--ProjectA
|-docker-compose.yml (builds ServiceA & ServiceB)
|--Services
|--PackageA
|-src
|-index.js
|-package.json
|--ServiceA
|-src
|-index.js
|-Dockerfile
|-package.json
|--ServiceB
|-src
|-index.js
|-Dockerfile
|-package.json
My docker-compose.yml
:
version: '3'
networks:
mynetwork:
services:
servicea:
build: ./../../Services/ServiceA
container_name: servicea
ports:
- ...
networks:
- mynetwork
serviceb:
build: ./../../Services/ServiceB
ports: serviceb
- ...
networks:
- mynetwork
In both services th Dockrfile
looks like this:
FROM node:16
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
# If you are building your code for production
# RUN npm ci --only=production
COPY . ./
EXPOSE ...
CMD [ "node", "index.js" ]
So my question is: Could I dockerize also PackageA
and create a volume with its content, and then using that volume in ServiceA & B
? How could I share volumes between containers?
CodePudding user response:
I don't think it's a good thing to go for this style of architecture. They are not microservices if they are coupled in this fashion. You would do better to publish your shared library or even do a bit of copying and pasting to duplicate the code.
However, technically speaking, it's possible. You could do something along these lines:
The Dockerfile, for the shared service, creates some dummy content in the directory /shared
.
FROM busybox
WORKDIR /shared
RUN echo "shared content" > /shared/data.txt
Then 2 services are started. Both mounting a shared volume. The shared service mounts the volume first because app-a has a depends_on
with condition
.
name: example
services:
shared:
build: ./
volumes: [ shared:/shared ]
app-a:
image: busybox
command: cat /shared/data.txt
volumes: [ shared:/shared ]
depends_on:
shared:
condition: service_completed_successfully
volumes:
shared:
$ docker compose up
[ ] Running 4/4
⠿ Network example_default Created 0.6s
⠿ Volume "example_shared" Created 0.0s
⠿ Container example-shared-1 Created 0.1s
⠿ Container example-app-a-1 Created 0.1s
Attaching to example-app-a-1, example-shared-1
example-shared-1 exited with code 0
example-app-a-1 | shared content
example-app-a-1 exited with code 0
When an empty named volume is mounted, the content of the container's file system is first copied into the volume and then its mounted.
That way, app-a, sees the shared content.
Sometimes you may also want to let the shared service populate the volume on startup, manually. Because what I am doing here is very specific to docker. It would not work in Kubernetes, for example. There you had to copy the shared content into the volume when the shared service starts.
shared:
image: busybox
command: sh -c 'echo "shared content" > /shared/data.txt'
volumes: [ shared:/shared ]