Wednesday, July 14, 2021

how to pass dockerfile argument from docker-compose file?

 It should be very convenient and dynamic, if we can set our environment variable on docker build time.

since I want to turn graphql playground on and off during the production deployment, I already use the 

NODE_ENV to control the playground feature in the .env file.

in .net file

NODE_ENV=dev

GraphQLModule.forRoot({
      playground: process.env.NODE_ENV === 'dev',
      debug: process.env.NODE_ENV === 'dev',
      autoSchemaFile: true,
    }),


we can use ARG to set a variable in the dockerfile that we can pass in during docker build run.

ARG node_env_var
ENV NODE_ENV=$node_env_var
RUN echo $node_env_var

here is the full content of Dockfile

FROM node:14 as production

ARG node_env_var
ENV NODE_ENV=$node_env_var
RUN echo $node_env_var

WORKDIR /usr/src/api

COPY package.json .
COPY yarn.lock .

RUN yarn global add @nestjs/cli

RUN yarn install --production=true

## install NIC s a computer networking utility for reading from and 
# writing to network connections using TCP or UDP.
RUN apt-get -q update && apt-get -qy install netcat

COPY . .

RUN yarn build

CMD ["sh", "-c", "yarn typeorm migration:run && yarn start:prod"]



in the Docker-compose.yml file we can set the args variable. when I run the deployment in the production environment, i can simply change the node_env_var: production

build: 
            context: server
            target: production
            dockerfile: Dockerfile
            args:
                node_env_var: dev

here is the docker-compse.yml file

version: "3.8"

services:
    mysqldb:
        image: mysql
        environment: 
            - MYSQL_ROOT_PASSWORD=Mys0l@123456
            - MYSQL_DATABASE=hyrecar
        ports: 
            - 3306:3306
        command: --default-authentication-plugin=mysql_native_password
        networks:
            - shared-network
        volumes: 
            - db-config:/etc/mysql
            - db-data:/var/lib/mysql
            - ./db/backup/files:/data_backup/data
       
    #acting as a proxy

    nginx:
        image: nginx:latest
        container_name: nginx-prod
        volumes: 
            - ./nginx/nginx.conf:/etc/nginx/nginx.conf
        ports: 
            - 81:80
        command: /bin/sh -c "nginx -g 'daemon off;'"    
        depends_on: 
            api-prod:
                condition: service_healthy
            app-prod:
                condition: service_started
        networks: 
            - shared-network

    api-prod:
        container_name: nestjs_api_prod
        image: nestjs_api_prod:1.0.0.0
        build: 
            context: server
            target: production
            dockerfile: Dockerfile
            args:
                node_env_var: dev
        command: sh -c './bin/wait-for -t 0 mysqldb:3306 -- yarn start:prod'
        depends_on: 
            - mysqldb
        networks: 
            - shared-network
        ports: 
            - 9000:9000
        restart: unless-stopped
        healthcheck:
            test: ["CMD", "curl", "http://api-prod:9000"]
            interval: 5s
            timeout: 3s
            retries: 6     
        
    app-prod:
        container_name: rect_app_prod
        image: rect_app_prod:1.0.0
        build:
            context: web
            target: production
            dockerfile: Dockerfile
        command: yarn run start:prod
        ports: 
            - 3000:3000
        networks: 
            - shared-network
        restart: unless-stopped

#intialize network
networks: 
    shared-network:

#Initializing docker compose volumes
volumes: 
    db-config:
    db-data:


for development and test environment deployment.

set node_env_var: dev in docker-compose.yml 

run docker-compose build to rebuilt the container

execute docker-compose up to run all containers

in the production, we just need to change node_env_var: production

then we can run docker-compose build & docker-compose up to turn off graphql playground feature for security reason.

 Please Note you can not simply update the variable in the docker-compose yaml file and run docker-compose up since the variable is passing in at docker-compose build time, not the run time. so We have to run docker-compose build process to take the effect.



No comments:

Post a Comment