1

Let's suppose there are two services and they have several volumes defined. But most of those volumes are used on both services:

version: '3'
services:
  service1:
    image: node:lts-alpine
    working_dir: /
    volumes:
      - ./package.json:/package.json
      - ./tsconfig.json:/tsconfig.json
      - ./packages:/packages
      - ./node_modules:/node_modules
      - ./services/service1:/services/service1
    command: yarn service1:start

  service2:
    image: node:lts-alpine
    working_dir: /
    volumes:
      - ./package.json:/package.json
      - ./tsconfig.json:/tsconfig.json
      - ./packages:/packages
      - ./node_modules:/node_modules
      - ./services/service2:/services/service2
    command: yarn service2:start

Is there a way to prevent this duplication?

I would love to do something like this:

version: '3'
services:
  service1:
    image: node:lts-alpine
    working_dir: /
    volumes:
      - myVolumeList
      - ./services/service1:/services/service1
    command: yarn start

  service2:
    image: node:lts-alpine
    working_dir: /
    volumes:
      - myVolumeList
      - ./services/service2:/services/service2
    command: yarn start

myVolumeList:
  - ./package.json:/package.json
  - ./tsconfig.json:/tsconfig.json
  - ./packages:/packages
  - ./node_modules:/node_modules

Edit: I use docker compose for local development only. Volumes are great for me because changing source code files will automatically restart my services. Thus copying files once isn't enough

Florian Ludewig
  • 4,338
  • 11
  • 71
  • 137

2 Answers2

1

The code for your application should generally be in a Docker image. You can launch multiple containers from the same image, possibly with different command:. For example, you might write a Dockerfile like:

FROM node:lts-alpine
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install
COPY ./ ./
CMD yarn start

Having described this image, you can reference it in the docker-compose.yml, overriding the command: for each service:

version: '3'
services:
  service1:
    build: .
    command: 'yarn service1:start'
  service2:
    build: .
    command: 'yarn service2:start'

(Compose will probably try to build a separate image for each service, but because of Docker layer caching, "building" the service2 image will run very quickly and wind up with a second tag on the same image.)

This setup needs no bind-mounts at all, and if you push the built images to a Docker registry, you can run them on a system without the application code or even Node available.

David Maze
  • 130,717
  • 29
  • 175
  • 215
  • That makes sense. But I use docker compose for local dev only. I use volumes because after changing source code the services will automatically restart. Thus copying the files isn't enough for (I should have mentioned this in the question) – Florian Ludewig May 01 '20 at 18:46
1
  1. Natively, you can do:

Maybe this solve your problem.

version: "3"

services:
  srv1:
    image: someimage
    volumes:
      - data:/data
  srv2:
    image: someimage
    volumes:
      - data:/data

volumes:
  data:
  1. There's a plugin - https://github.com/MatchbookLab/local-persist (read it before use!)- that let you change the volume mountpoint.

Basicaly, install it: curl -fsSL https://raw.githubusercontent.com/MatchbookLab/local-persist/master/scripts/install.sh | sudo bash

Then create a volume: docker volume create -d local-persist -o mountpoint=/data/images --name=images

Then use as many containers as you want:

docker run -d -v images:/path/to/images/on/one/ one
docker run -d -v images:/path/to/images/on/two/ two

If you whant to use docker-compose, there's a example:

version: '3'

services:
  one:
    image: alpine
    working_dir: /one/
    command: sleep 600
    volumes:
      - data:/one/

  two:
    image: alpine
    working_dir: /two/
    command: sleep 600
    volumes:
      - data:/two/

volumes:
  data:
    driver: local-persist
    driver_opts:
      mountpoint: /data/local-persist/data

Almost the same question here: docker volume custom mount point

  1. This only work on docker-compose version '2':
version: '2'
services:

  srv1:
    image: sometag
    volumes_from:
      - data

  srv2:
    image: sometag
    volumes_from:
      - data

  data:
    image: sometag
    volumes:
      - ./code-in-host:/code