Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## intelij idea
.idea

.DS_Store
.DS_Store
12 changes: 12 additions & 0 deletions backend/Dockerfile.dev
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
FROM amazoncorretto:17-alpine

ARG JAR_FILE=backend/build/libs/backend-0.0.1-SNAPSHOT.jar
RUN apk add --no-cache bash

WORKDIR /app

COPY ${JAR_FILE} app.jar
COPY script/wait-for-it.sh /app/config/wait-for-it.sh
RUN chmod +x /app/config/wait-for-it.sh

ENTRYPOINT ["/app/config/wait-for-it.sh", "db:3306", "--", "java", "-Dspring.profiles.active=dev", "-Duser.timezone=Asia/Seoul", "-jar", "app.jar"]
30 changes: 30 additions & 0 deletions script/docker-compose-dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
services:
db:
image: mysql:8.0
container_name: backend_mysql
restart: always
environment:
- MYSQL_ROOT_PASSWORD=1234
- MYSQL_DATABASE=app_db
- MYSQL_USER=sa
- MYSQL_PASSWORD=1234
- TZ=Asia/Seoul
command:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
ports:
- "3307:3306"

api:
depends_on:
- db
image: backend:latest
container_name: backend_api
ports:
- "8080:8080"
environment:
- SPRING_DATASOURCE_URL=jdbc:mysql://backend_mysql:3306/app_db
- SPRING_DATASOURCE_USERNAME=sa
- SPRING_DATASOURCE_PASSWORD=1234
- SPRING_SQL_INIT_MODE=never
- TZ=Asia/Seoul
46 changes: 46 additions & 0 deletions script/setup_and_run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/bin/bash
set -e

SCRIPT_DIR=$(pwd)
BACKEND_DIR=$(cd "$(dirname "$0")/.." && pwd)/backend
BASE_DIR=$(cd "$(dirname "$0")/.." && pwd)

IMAGE_NAME="backend"
IMAGE_TAG="latest"
JAR_FILE="backend/build/libs/backend-0.0.1-SNAPSHOT.jar"
DOCKERFILE="${BACKEND_DIR}/Dockerfile.dev"

cd ${BACKEND_DIR}

echo "Gradle 빌드 중..."

chmod +x ${BACKEND_DIR}/gradlew
${BACKEND_DIR}/gradlew clean build

echo "${IMAGE_NAME}/${IMAGE_TAG} 이미지를 빌드 중..."

docker build --build-arg --no-cache -f "${DOCKERFILE}" -t "${IMAGE_NAME}:${IMAGE_TAG}" "${BASE_DIR}"

echo "도커 이미지 빌드 완료"
Comment on lines +20 to +24
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

⚠️ Potential issue

Missing Build Argument in Docker Build Command

The docker build command currently includes --build-arg without a key–value pair, which means the intended build argument (likely to pass JAR_FILE) isn’t actually provided. If the goal is to pass the JAR_FILE variable to the Docker build, update the command as follows:

-docker build --build-arg --no-cache -f "${DOCKERFILE}" -t "${IMAGE_NAME}:${IMAGE_TAG}" "${BASE_DIR}"
+docker build --no-cache --build-arg JAR_FILE="${JAR_FILE}" -f "${DOCKERFILE}" -t "${IMAGE_NAME}:${IMAGE_TAG}" "${BASE_DIR}"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
echo "${IMAGE_NAME}/${IMAGE_TAG} 이미지를 빌드 중..."
docker build --build-arg --no-cache -f "${DOCKERFILE}" -t "${IMAGE_NAME}:${IMAGE_TAG}" "${BASE_DIR}"
echo "도커 이미지 빌드 완료"
echo "${IMAGE_NAME}/${IMAGE_TAG} 이미지를 빌드 중..."
docker build --no-cache --build-arg JAR_FILE="${JAR_FILE}" -f "${DOCKERFILE}" -t "${IMAGE_NAME}:${IMAGE_TAG}" "${BASE_DIR}"
echo "도커 이미지 빌드 완료"


# ----------------------------------------------

cd ${SCRIPT_DIR}
echo "👉 docker-compose를 사용하여 API와 MySQL 컨테이너를 실행합니다..."

API_CONTAINER_NAME="backend_api"
DB_CONTAINER_NAME="backend_mysql"

EXISTING_CONTAINER=$(docker ps -aq --filter "name=^/${API_CONTAINER_NAME}$")
if [ -n "$EXISTING_CONTAINER" ]; then
echo "👉 기존 컨테이너 '$API_CONTAINER_NAME' 발견: 제거합니다..."
docker rm -f "$EXISTING_CONTAINER"
fi
EXISTING_CONTAINER=$(docker ps -aq --filter "name=^/${DB_CONTAINER_NAME}$")
if [ -n "$EXISTING_CONTAINER" ]; then
echo "👉 기존 컨테이너 '$DB_CONTAINER_NAME' 발견: 제거합니다..."
docker rm -f "$EXISTING_CONTAINER"
fi

docker-compose -f docker-compose-dev.yml up -d
echo "✅ 모든 서비스가 백그라운드에서 실행 중입니다."
182 changes: 182 additions & 0 deletions script/wait-for-it.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
#!/usr/bin/env bash
# Use this script to test if a given TCP host/port are available

WAITFORIT_cmdname=${0##*/}

echoerr() { if [[ $WAITFORIT_QUIET -ne 1 ]]; then echo "$@" 1>&2; fi }

usage()
{
cat << USAGE >&2
Usage:
$WAITFORIT_cmdname host:port [-s] [-t timeout] [-- command args]
-h HOST | --host=HOST Host or IP under test
-p PORT | --port=PORT TCP port under test
Alternatively, you specify the host and port as host:port
-s | --strict Only execute subcommand if the test succeeds
-q | --quiet Don't output any status messages
-t TIMEOUT | --timeout=TIMEOUT
Timeout in seconds, zero for no timeout
-- COMMAND ARGS Execute command with args after the test finishes
USAGE
exit 1
}

wait_for()
{
if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then
echoerr "$WAITFORIT_cmdname: waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT"
else
echoerr "$WAITFORIT_cmdname: waiting for $WAITFORIT_HOST:$WAITFORIT_PORT without a timeout"
fi
WAITFORIT_start_ts=$(date +%s)
while :
do
if [[ $WAITFORIT_ISBUSY -eq 1 ]]; then
nc -z $WAITFORIT_HOST $WAITFORIT_PORT
WAITFORIT_result=$?
else
(echo -n > /dev/tcp/$WAITFORIT_HOST/$WAITFORIT_PORT) >/dev/null 2>&1
WAITFORIT_result=$?
fi
if [[ $WAITFORIT_result -eq 0 ]]; then
WAITFORIT_end_ts=$(date +%s)
echoerr "$WAITFORIT_cmdname: $WAITFORIT_HOST:$WAITFORIT_PORT is available after $((WAITFORIT_end_ts - WAITFORIT_start_ts)) seconds"
break
fi
sleep 1
done
return $WAITFORIT_result
}

wait_for_wrapper()
{
# In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692
if [[ $WAITFORIT_QUIET -eq 1 ]]; then
timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --quiet --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT &
else
timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT &
fi
WAITFORIT_PID=$!
trap "kill -INT -$WAITFORIT_PID" INT
wait $WAITFORIT_PID
WAITFORIT_RESULT=$?
if [[ $WAITFORIT_RESULT -ne 0 ]]; then
echoerr "$WAITFORIT_cmdname: timeout occurred after waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT"
fi
return $WAITFORIT_RESULT
}
Comment on lines +52 to +68
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Timeout Handling with Wait Wrapper

The wait_for_wrapper function uses the timeout command to ensure graceful termination if the wait exceeds the defined timeout.
Important:
Line 61 uses a trap command that presently expands variables immediately. To ensure the variable is expanded only when the signal is received, change line 61 to use single quotes:

-trap "kill -INT -$WAITFORIT_PID" INT
+trap 'kill -INT -$WAITFORIT_PID' INT

[shellcheck]

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
wait_for_wrapper()
{
# In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692
if [[ $WAITFORIT_QUIET -eq 1 ]]; then
timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --quiet --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT &
else
timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT &
fi
WAITFORIT_PID=$!
trap "kill -INT -$WAITFORIT_PID" INT
wait $WAITFORIT_PID
WAITFORIT_RESULT=$?
if [[ $WAITFORIT_RESULT -ne 0 ]]; then
echoerr "$WAITFORIT_cmdname: timeout occurred after waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT"
fi
return $WAITFORIT_RESULT
}
wait_for_wrapper()
{
# In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692
if [[ $WAITFORIT_QUIET -eq 1 ]]; then
timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --quiet --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT &
else
timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT &
fi
WAITFORIT_PID=$!
- trap "kill -INT -$WAITFORIT_PID" INT
+ trap 'kill -INT -$WAITFORIT_PID' INT
wait $WAITFORIT_PID
WAITFORIT_RESULT=$?
if [[ $WAITFORIT_RESULT -ne 0 ]]; then
echoerr "$WAITFORIT_cmdname: timeout occurred after waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT"
fi
return $WAITFORIT_RESULT
}
🧰 Tools
🪛 Shellcheck (0.10.0)

[warning] 61-61: Use single quotes, otherwise this expands now rather than when signalled.

(SC2064)


# process arguments
while [[ $# -gt 0 ]]
do
case "$1" in
*:* )
WAITFORIT_hostport=(${1//:/ })
WAITFORIT_HOST=${WAITFORIT_hostport[0]}
WAITFORIT_PORT=${WAITFORIT_hostport[1]}
shift 1
;;
--child)
WAITFORIT_CHILD=1
shift 1
;;
-q | --quiet)
WAITFORIT_QUIET=1
shift 1
;;
-s | --strict)
WAITFORIT_STRICT=1
shift 1
;;
-h)
WAITFORIT_HOST="$2"
if [[ $WAITFORIT_HOST == "" ]]; then break; fi
shift 2
;;
--host=*)
WAITFORIT_HOST="${1#*=}"
shift 1
;;
-p)
WAITFORIT_PORT="$2"
if [[ $WAITFORIT_PORT == "" ]]; then break; fi
shift 2
;;
--port=*)
WAITFORIT_PORT="${1#*=}"
shift 1
;;
-t)
WAITFORIT_TIMEOUT="$2"
if [[ $WAITFORIT_TIMEOUT == "" ]]; then break; fi
shift 2
;;
--timeout=*)
WAITFORIT_TIMEOUT="${1#*=}"
shift 1
;;
--)
shift
WAITFORIT_CLI=("$@")
break
;;
--help)
usage
;;
*)
echoerr "Unknown argument: $1"
usage
;;
esac
done

if [[ "$WAITFORIT_HOST" == "" || "$WAITFORIT_PORT" == "" ]]; then
echoerr "Error: you need to provide a host and port to test."
usage
fi

WAITFORIT_TIMEOUT=${WAITFORIT_TIMEOUT:-15}
WAITFORIT_STRICT=${WAITFORIT_STRICT:-0}
WAITFORIT_CHILD=${WAITFORIT_CHILD:-0}
WAITFORIT_QUIET=${WAITFORIT_QUIET:-0}

# Check to see if timeout is from busybox?
WAITFORIT_TIMEOUT_PATH=$(type -p timeout)
WAITFORIT_TIMEOUT_PATH=$(realpath $WAITFORIT_TIMEOUT_PATH 2>/dev/null || readlink -f $WAITFORIT_TIMEOUT_PATH)

WAITFORIT_BUSYTIMEFLAG=""
if [[ $WAITFORIT_TIMEOUT_PATH =~ "busybox" ]]; then
WAITFORIT_ISBUSY=1
# Check if busybox timeout uses -t flag
# (recent Alpine versions don't support -t anymore)
if timeout &>/dev/stdout | grep -q -e '-t '; then
WAITFORIT_BUSYTIMEFLAG="-t"
fi
else
WAITFORIT_ISBUSY=0
fi
Comment on lines +145 to +158
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Busybox Timeout Detection

The script determines whether the available timeout command is from busybox, adjusting flags accordingly.
Note:
On line 153, the redirection &>/dev/stdout combined with piping to grep may not work as intended since the redirection overrides the pipe’s input. Consider capturing the output first or using tee:

- if timeout &>/dev/stdout | grep -q -e '-t '; then
+ if timeout --help 2>&1 | tee /dev/null | grep -q -e '-t '; then

[shellcheck]

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
WAITFORIT_TIMEOUT_PATH=$(type -p timeout)
WAITFORIT_TIMEOUT_PATH=$(realpath $WAITFORIT_TIMEOUT_PATH 2>/dev/null || readlink -f $WAITFORIT_TIMEOUT_PATH)
WAITFORIT_BUSYTIMEFLAG=""
if [[ $WAITFORIT_TIMEOUT_PATH =~ "busybox" ]]; then
WAITFORIT_ISBUSY=1
# Check if busybox timeout uses -t flag
# (recent Alpine versions don't support -t anymore)
if timeout &>/dev/stdout | grep -q -e '-t '; then
WAITFORIT_BUSYTIMEFLAG="-t"
fi
else
WAITFORIT_ISBUSY=0
fi
WAITFORIT_TIMEOUT_PATH=$(type -p timeout)
WAITFORIT_TIMEOUT_PATH=$(realpath $WAITFORIT_TIMEOUT_PATH 2>/dev/null || readlink -f $WAITFORIT_TIMEOUT_PATH)
WAITFORIT_BUSYTIMEFLAG=""
if [[ $WAITFORIT_TIMEOUT_PATH =~ "busybox" ]]; then
WAITFORIT_ISBUSY=1
# Check if busybox timeout uses -t flag
# (recent Alpine versions don't support -t anymore)
- if timeout &>/dev/stdout | grep -q -e '-t '; then
+ if timeout --help 2>&1 | tee /dev/null | grep -q -e '-t '; then
WAITFORIT_BUSYTIMEFLAG="-t"
fi
else
WAITFORIT_ISBUSY=0
fi
🧰 Tools
🪛 Shellcheck (0.10.0)

[error] 153-153: This redirection overrides the output pipe. Use 'tee' to output to both.

(SC2260)


if [[ $WAITFORIT_CHILD -gt 0 ]]; then
wait_for
WAITFORIT_RESULT=$?
exit $WAITFORIT_RESULT
else
if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then
wait_for_wrapper
WAITFORIT_RESULT=$?
else
wait_for
WAITFORIT_RESULT=$?
fi
fi

if [[ $WAITFORIT_CLI != "" ]]; then
if [[ $WAITFORIT_RESULT -ne 0 && $WAITFORIT_STRICT -eq 1 ]]; then
echoerr "$WAITFORIT_cmdname: strict mode, refusing to execute subprocess"
exit $WAITFORIT_RESULT
fi
exec "${WAITFORIT_CLI[@]}"
else
exit $WAITFORIT_RESULT
fi