8

I have an NX monorepo with 2 apps:

  • Shop
  • Landing

I wish to use docker-compose to run my entire environment with eventually some APIs and a database etc etc.

I created a docker-file that takes arguments and could be re-used to to run multiple angular apps in Nx:

# base image
FROM node

ARG APP


# # install chrome for protractor tests
# RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -
# RUN sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list'
# RUN apt-get update && apt-get install -yq google-chrome-stable
# set working directory
WORKDIR /app

# add `/app/node_modules/.bin` to $PATH
ENV PATH /app/node_modules/.bin:$PATH

# install and cache app dependencies
COPY package.json /app/package.json
COPY decorate-angular-cli.js /app/decorate-angular-cli.js
RUN npm install
RUN npm install -g @angular/cli@latest
RUN npm install reflect-metadata tslib rxjs @nestjs/platform-express

# add app
COPY . /app
# start app
CMD npm start $APP -- --host 0.0.0.0 --port 4200 --disableHostCheck=true --poll 100

and I created a docker-compose file that sets up an .net 5 API and the 2 web applications:

version: '3.4'

services:
  sletsgo.user.api:
    image: ${DOCKER_REGISTRY-}sletsgo.user.api
    build:
      context: .
      dockerfile: SletsGo.User.Api/Dockerfile
    ports:
      - "5000:2000"
      - "444:443"

  sletsgo.shop:
    container_name: 'SletsGo.Shop'
    image: ${DOCKER_REGISTRY}sletsgo.shop:dev
    build:
        context: SletsGo
        dockerfile: .docker/Dockerfile
        args:
            - APP=shop
    ports:
        - '4000:4200'
    #volumes:
    #    - sletsgo-web:/app
    #    - '/app/node_modules'

  sletsgo.landing:
    container_name: 'SletsGo.Landing'
    image: ${DOCKER_REGISTRY}sletsgo.landing:dev
    build:
        context: SletsGo
        dockerfile: .docker/Dockerfile
        args:
            - APP=landing
    ports:
        - '4100:4200'
  #  volumes:
  #      - sletsgo-web:/app
  #      - '/app/node_modules'

 


#volumes:
# sletsgo-web:
#    driver: local
#    driver_opts:
#      type: local
#      device: ./SletsGo
#      o: bind

Please note that a lot of lines are commented out. The issue is that if I run this docker-compose i get 2 instances of the shop application ran.

screenshot showing 2 instaces of shop

How can i fix this?

P.S. I also imagine that using volumes i might be able to simplify things a lot. But the mounting i tried failed because im using linux containers on a windows machine. If someone is willing to help me to that next level i would like that very much, but for now i just want to run both the web applications.

Dylan Snel
  • 671
  • 2
  • 7
  • 26
  • Try adding the following property to your landing service: `command: npm start landing -- --host 0.0.0.0 --port 4200 --disableHostCheck=true --poll 100` – anemyte Apr 08 '21 at 09:10
  • Add it where exactlyt? – Dylan Snel Apr 08 '21 at 10:36
  • `services -> sletsgo.landing -> command: npm start landing -- --host 0.0.0.0 --port 4200 --disableHostCheck=true --poll 100`. The thing is, `APP` argument may be empty when you start the container. `command` in service definition overrides `CMD` from Dockerfile. – anemyte Apr 08 '21 at 10:55
  • Do i then not use the dockerfile anymore? – Dylan Snel Apr 09 '21 at 09:44
  • No, you still need the Dockerfile but if it worked it proved that the problem is in argument missing. Did it help? – anemyte Apr 09 '21 at 09:49
  • Persisting the [`APP` values in the environment during the build should solve the issue](https://docs.docker.com/engine/reference/builder/#using-arg-variables). Otherwise you can [overwrite the `command` for both services in the `docker-compose.yaml`](https://docs.docker.com/compose/compose-file/compose-file-v3/#command). – masseyb Apr 12 '21 at 18:00
  • why you need `--host 0.0.0.0` in the docker file if you are mapping the port in the Docker compose? – Nikhil Walvekar Apr 12 '21 at 18:03
  • @anemyte your solution works! strange since when i had an echo in my dockerfile it would show it. Couldnt i just remove the dockerfile all together if i had a volume mounted? – Dylan Snel Apr 14 '21 at 18:17
  • @NikhilWalvekar Idk this is how i got it working before. maybe its redundant now. – Dylan Snel Apr 14 '21 at 18:19
  • @NikhilWalvekar Doesnt work without d--host 0.0.0.0 – Dylan Snel Apr 14 '21 at 18:39

1 Answers1

7

TL;DR

ARG's are build time variables. You can persist the ARG's value in the images environment during the build or override the services[*].command in the docker-compose.yaml.


Persist in the environment

You can persist an environment variable set from a --build-arg in the images environment during the build:

FROM alpine:3
ARG APP
ENV APP=${APP}
CMD echo $APP

Build the docker image: docker build --rm --build-arg APP=123 -t so:66935830 .

Run the docker container: docker run --rm -it so:66935830

docker run with environment variable set from --build-arg

Override the command

You can override the command for each service in the docker-compose.yaml:

version: '3.7'
services:
  a:
    image: 'a'
    build:
      context: '.'
    command: ['echo', '123']
  b:
    image: 'b'
    build:
      context: '.'
    command: ['echo', '456']

docker-compose run command override

masseyb
  • 3,745
  • 1
  • 17
  • 29