Search code examples
node.jsdockerdocker-composedockerfiledirectory-structure

Can I use a docker container to keep static files so other docker containers can acces to it?


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?


Solution

  • 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 ]