1

Тема: Docker для спрощення життя розробників

Є типовий веб-додаток, бек на NodeJs, фронт на ReacJs. В якості бази даних використовується MongoDB.
Треба якось налаштувати то все так, аби спростити життя розробникам.
Таке завдання в мене вперше в житті, тому це одночасно дуже цікаво, і  не дуже зрозуміло.

Поки що я намагаюсь спростити життя для розробки беку.

Ідея така: робимо image з mongo, щоб не треба було встановлювати то самому, далі робимо image з потрібної нам node, аби розробникам не треба було переживати через не таку версію ноди, або ще щось.
Далі створюю volume, аби він в собі містив весь код, який може змінюватись.

Тобто, тепер розробнику не треба встановлювати ноду та налаштовувати монгодб, і завдяки тому, що додаток запускається через nodemon - будь-які зміни в файлах з кодом будуть перезапускати додаток всередині контейнера.

Але я пішов далі, бо локальну базу даних треба начиняти якоюсь інформацією, перш ніж запускати додаток, котрий буде з нею працювати.

Ідея така.
Спочатку запускаємо mongo, ми хочемо, аби зміни до цієї бази даних зберігалися між запусками, тому під'єднуємо volume до /data/db (це там файли бази даних будуть зберігатися, воно ніби у нашій файловій системі, але контейнер це все може бачити), після цього запускаємо контейнер, котрий почекає, доки база даних підніметься, для цього я нагуглив такий Dockerfile, котрий виконує такий скрипт.

FROM alpine

RUN apk add --update netcat-openbsd
COPY wait-for-mongo.sh .
RUN chmod 700 ./wait-for-mongo.sh

CMD ["/bin/sh", "./wait-for-mongo.sh"]
#!/bin/sh

: ${MONGODB_HOST:=mongo}
: ${MONGODB_PORT:=27017}

until nc -z $MONGODB_HOST $MONGODB_PORT
do
  echo "Waiting for Mongo ($MONGODB_HOST:$MONGODB_PORT) to start..."
  sleep 0.5
done

eval $*

Після цього, коли ми знаємо, що база даних працює, виконується етап наповнення бази даних власне даними. Я мучився з цим трішки, бо хотів використати ось такого скрипта

#!/bin/sh

: ${MONGODB_HOST:=mongo}
: ${MONGODB_PORT:=27017}

if [ $(mongo MONGODB_HOST:MONGODB_PORT --eval 'db.getMongo().getDBNames().indexOf("my-db-name")' --quiet) -lt 0 ]; then
    echo "Database does not exist."
    mongorestore --host MONGODB_HOST --port MONGODB_PORT --db my-db-name /data
else
    echo "Database exists."
fi

Він мав би спочатку перевірити, чи база даних існує, і якщо так - тоді нічого не робимо, бо ми не хочемо перезаписувати всю базу даних кожного разу, коли перезапускаємо docker-compose, а якщо не існує - то створюємо її, і відразу наповнюємо даними.

Але як бачите, для цього нам треба

mongo

, а як його встановити на alpine - я хз, тому замість alpine для цієї задачі я використав ще один mongo контейнер, але в ньому той скрипт не виконується, матюкається на

[

.

Тому поки що я завис на цьому етапі.

Файл docker-compose виглядає так.

version: '3'
services:
  mongo:
    container_name: my-db
    image: mongo
    volumes:
      - ./db/data:/data/db
    logging:
      driver: none
    restart: always

  mongo-wait:
    build: ./db
    environment:
      - MONGODB_HOST=mongo
      - MONGODB_PORT=27017
    volumes:
      - ./db/:/data
    depends_on:
      - mongo

  mongo-seed:
    build: ./db/seed
    volumes:
      - ./db/seed/my-db:/data
    depends_on:
      - mongo-wait

  backend:
    container_name: my_backend
    build:
      context: ./src
      dockerfile: Dockerfile
    ports:
      - '3000:3000'
    volumes:
      - .:/app
    depends_on:
      - mongo-wait

mongo-seed:

FROM mongo

COPY ./seed-db.sh .
RUN chmod 700 seed-db.sh

ENTRYPOINT ["/bin/sh", "seed-db.sh"]

в seed-db.sh зараз є тільки рядок з mongorestore --host ..., без перевірок, чи база існує, бо якщо існує, воно просто покаже купу помилок, і не перезапише базу даних, але цей процес займає кілька секунд, тому хз, чи його так можна лишати.
my_backend:

FROM node:15

WORKDIR /app

RUN npm install

COPY . .

ENV PORT=3000

EXPOSE 3000

CMD ["npm", "start"]

Що я зробив не так, і як це все можна покращити?

2

Re: Docker для спрощення життя розробників

FakiNyan написав:

замість alpine для цієї задачі я використав ще один mongo контейнер, але в ньому той скрипт не виконується, матюкається на

[

.

Спробуйте інсталювати у контейнер test -- може там нема.

Також я б рекомендував завжди ставити у bash-скрипті shebang /bin/bash, а не /bin/sh, бо мало який там за замовченням shell.

Подякували: FakiNyan1

3

Re: Docker для спрощення життя розробників

Ось так запрацювало

#!/bin/bash

if [ $(mongo mongo:27017 --eval 'db.getMongo().getDBNames().indexOf("my-db-name")' --quiet) -lt 0 ]; then 
   echo "Database does not exist.";
   mongorestore --host mongo --port 27017 --db my-db-name /data --quiet
else
   echo "Database exists.";
fi

Але змінні шось ніяк не хотіли працювати, тому довелось вручну хост і порт записати.

4

Re: Docker для спрощення життя розробників

Так спитайте про змінні на форумі. Ви ж знаєте, як правильно питання ставити.

5

Re: Docker для спрощення життя розробників

koala написав:

Так спитайте про змінні на форумі. Ви ж знаєте, як правильно питання ставити.

Та то не головне зараз, я то потім колись пофіксю, якшо дуже треба буде

6

Re: Docker для спрощення життя розробників

FakiNyan написав:

Ось так запрацювало

#!/bin/bash

if [ $(mongo mongo:27017 --eval 'db.getMongo().getDBNames().indexOf("my-db-name")' --quiet) -lt 0 ]; then 
   echo "Database does not exist.";
   mongorestore --host mongo --port 27017 --db my-db-name /data --quiet
else
   echo "Database exists.";
fi

Але змінні шось ніяк не хотіли працювати, тому довелось вручну хост і порт записати.


Уточніть, будь ласка, про які змінні йдеться? Змінні середовища прописані в Dockerfile?

7

Re: Docker для спрощення життя розробників

bebyk написав:
FakiNyan написав:

Ось так запрацювало

#!/bin/bash

if [ $(mongo mongo:27017 --eval 'db.getMongo().getDBNames().indexOf("my-db-name")' --quiet) -lt 0 ]; then 
   echo "Database does not exist.";
   mongorestore --host mongo --port 27017 --db my-db-name /data --quiet
else
   echo "Database exists.";
fi

Але змінні шось ніяк не хотіли працювати, тому довелось вручну хост і порт записати.


Уточніть, будь ласка, про які змінні йдеться? Змінні середовища прописані в Dockerfile?

Ті, шо раніше були записані в самому скрипті ось так

: ${MONGODB_HOST:=mongo}
: ${MONGODB_PORT:=27017}
...

8

Re: Docker для спрощення життя розробників

MONGODB_HOST=mongo
MONGODB_PORT=27017
mongorestore --host $MONGODB_HOST --port $MONGODB_PORT --db my-db-name /data --quiet

Присвоювання - без $. Звертання до значення - з $.

Подякували: FakiNyan, bebyk, leofun013

9 Востаннє редагувалося FakiNyan (13.10.2021 15:48:39)

Re: Docker для спрощення життя розробників

koala написав:
MONGODB_HOST=mongo
MONGODB_PORT=27017
mongorestore --host $MONGODB_HOST --port $MONGODB_PORT --db my-db-name /data --quiet

Присвоювання - без $. Звертання до значення - з $.

Все одно не робе, саме в тому рядку, де з if. То матюкається на [, то на те, що MONGODB_PORT в якомусь не такому форматі, воно очікує інтеджер, а отримує шось інше
Робе, то в мене не завжди новий image білдився, чи шось таке...

10

Re: Docker для спрощення життя розробників

FakiNyan написав:

то в мене не завжди новий image білдився, чи шось таке...

Welcome to Containers!  *HI*

Подякували: FakiNyan1