У меня есть два контейнера Docker:
- b-db - содержит мою базу данных
- b-комбинированный - содержит мой вебприложение и тесты, которые запускаются после запуска контейнера.
Я использую файл docker-compose.yml для запуска обоих контейнеров.
version: '3'
services:
db:
build:
context: .
dockerfile: ./docker/db/Dockerfile
container_name: b-db
restart: unless-stopped
volumes:
- dbdata:/data/db
ports:
- "27017:27017"
networks:
- app-network
combined:
build:
context: .
dockerfile: ./docker/combined/Dockerfile
container_name: b-combined
restart: unless-stopped
env_file: .env
ports:
- "5000:5000"
- "8080:8080"
networks:
- app-network
depends_on:
- db
networks:
app-network:
driver: bridge
volumes:
dbdata:
node_modules:
Яиспользуя Jenkins для запуска моих контейнеров и запуска тестов с помощью следующей команды. Я использую --exit-code-from
, как указано в SO сообщениях от здесь , здесь и здесь .
docker-compose up --build --exit-code-from combined
Ниже приводится то, что мойJenkinsfile выглядит следующим образом.
pipeline {
agent any
environment {
CI = 'true'
}
stages {
stage('Test') {
steps {
sh 'docker-compose up --build --exit-code-from combined'
}
}
}
}
Когда мои тесты запускаются, кажется, что b-комбинированный завершается, как и ожидалось, с ненулевым кодом ошибки, который отображается на консоли, как показано ниже. Это вызывает отключение обоих контейнеров, что также является ожидаемым поведением.
b-комбинированный, выход с кодом 2
Остановка b-комбинированного ...
Остановка b-db ...
Остановка b-db ... выполнено Отмена при выходе из контейнера ...
Почему Дженкинс все еще показывает, что тесты пройдены(см. скриншот ниже)? Разве Дженкинсу не удалось после ненулевого выхода из команды docker-compose up --build --exit-code-from combined
?
Кроме того, когда явыполнить следующее сразу же после того, как я локально запустил вышеупомянутую команду docker-compose в моей командной строке (не в Jenkins), я получаю код ошибки 0, который подтверждает, что проблема не в Jenkins, а скорее в том, что docker-compose не распознает, что яЯ завершаю работу init.sh
с ненулевым кодом выхода.
$ echo $?
0
Согласно приведенному ниже предложению @LinPy, я выполнил следующую команду локально на своей машине и в Jenkins.
docker-compose up -d --build db && docker-compose up --build combined || exit 2; echo $?
Вывод, который я получил, выглядит следующим образом. Последняя строка представляет собой вывод echo $?
, который показывает, что скрипт по-прежнему завершается с кодом ошибки 0.
b-combined | Mongoose disconnected
b-combined | TEST ENDED WITH EXIT CODE OF: 2
b-combined | EXITING SCRIPT WITH EXIT CODE OF: 2
b-combined exited with code 2
0
Ниже приведен снимок экрана Jenkins после выполнения вышеуказанной команды:
Чтобы помочь с отладкой, ниже приведен Dockerfile для службы combined
в docker-compose.yml
.
RUN npm install
COPY . .
EXPOSE 5000
RUN npm install -g history-server nodemon
RUN npm run build-test
EXPOSE 8080
COPY ./docker/combined/init.sh /scripts/init.sh
RUN ["chmod", "+x", "/scripts/init.sh"]
ENTRYPOINT [ "/scripts/init.sh" ]
Ниже приводится то, чтов моем файле init.sh
.
#!/bin/bash
# Start front end server
history-server dist -p 8080 &
front_pid=$!
# Start back end server that interacts with DB
nodemon -L server &
back_pid=$!
# Run tests
NODE_ENV=test $(npm bin)/cypress run --config video=false --browser chrome
# Error code of the test
test_exit_code=$?
echo "TEST ENDED WITH EXIT CODE OF: $test_exit_code"
# End front and backend server
kill -9 $front_pid
kill -9 $back_pid
# Exit with the error code of the test
echo "EXITING SCRIPT WITH EXIT CODE OF: $test_exit_code"
exit "$test_exit_code"
Ниже приведен файл Docker для моей службы db
. Все, что он делает, это копирует некоторые локальные данные в контейнер Docker и затем инициализирует базу данных с этими данными.
FROM mongo:3.6.14-xenial
COPY ./dump/ /tmp/dump/
COPY mongo_restore.sh /docker-entrypoint-initdb.d/
RUN chmod 777 /docker-entrypoint-initdb.d/mongo_restore.sh
Ниже приведено то, что находится в mongo_restore.sh
.
#!/bin/bash
# Creates db using copied data
mongorestore /tmp/dump
Следуя обновленному решению @LinPy, я попытался выполнить следующие шаги.
Ниже показано, как выглядит мой новый combined
Dockerfile:
RUN npm install
COPY . .
EXPOSE 5000
RUN npm install -g history-server nodemon
RUN npm run build-test
EXPOSE 8080
COPY ./docker/combined/init.sh /scripts/init.sh
RUN ["chmod", "+x", "/scripts/init.sh"]
ENTRYPOINT [ "/scripts/init.sh" ]
# NEW LINE ADDED HERE
CMD ["sh", "-c", "exit $(cat /scripts/exit_code)"]
Ниже показан мой новый init.sh
файл.
#!/bin/bash
# Start front end server
history-server dist -p 8080 &
front_pid=$!
# Start back end server that interacts with DB
nodemon -L server &
back_pid=$!
# Run tests
NODE_ENV=test $(npm bin)/cypress run --config video=false --browser chrome
# Error code of the test
test_exit_code=$?
echo "TEST ENDED WITH EXIT CODE OF: $test_exit_code"
# End front and backend server
kill -9 $front_pid
kill -9 $back_pid
# NEW LINES ADDED HERE
echo "$test_exit_code" > /scripts/exit_code
exec "$@"
# Exit with the error code of the test
echo "EXITING SCRIPT WITH EXIT CODE OF: $test_exit_code"
exit "$test_exit_code"
Наконец, я выполнил следующую команду:
docker-compose up -d --build db && docker-compose up --build combined || exit 2; echo $?
Вывод выглядит следующим образом- последняя строка (из вывода echo $?
) имеет код выхода 0.
b-combined | TEST ENDED WITH EXIT CODE OF: 2 ===========================
b-combined exited with code 2
0
РЕШЕНИЕ:
Я использовал более старую версию docker-compose(до v1.23.0). Как вы можете видеть в заметках о выпуске docker-compose, было несколько исправлений ошибок вокруг --exit-code-from
начиная с v1.23.0.