-
Notifications
You must be signed in to change notification settings - Fork 1
[BE-Feat] 백엔드 api 도커 컨테이너 실행 스크립트 구현 #92
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughThe changes reintroduce the Changes
Sequence Diagram(s)sequenceDiagram
participant Dev as Developer
participant Setup as setup_and_run.sh
participant Gradle as Gradle Build
participant Image as Docker Image Build
participant Compose as docker-compose
participant DB as MySQL Container (db)
participant API as API Container
participant Wait as wait-for-it.sh
Dev->>Setup: Execute setup_and_run.sh
Setup->>Gradle: Run Gradle build
Gradle-->>Setup: Build successful
Setup->>Image: Build Docker image using Dockerfile.dev
Image-->>Setup: Image built
Setup->>Compose: Start services with docker-compose
Compose->>DB: Launch MySQL container (db)
Compose->>API: Launch API container
API->>Wait: Invoke wait-for-it.sh to check DB readiness
Wait->>DB: Check connection on port 3306
DB-->>Wait: Connection established
Wait-->>API: Signal readiness and start Java application
Poem
Tip 🌐 Web search-backed reviews and chat
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (3)
script/setup_and_run.sh (1)
31-43: Container Cleanup and Conflict PreventionThe script checks for existing containers by name and removes them if found. This proactive cleanup avoids potential conflicts when starting new instances. Optionally, additional error handling/logging can help troubleshoot removal failures.
script/wait-for-it.sh (2)
70-132: Comprehensive Argument ParsingThe argument parsing loop robustly handles different input formats (e.g.,
host:port, flags, and long option formats). It correctly assigns values to variables likeWAITFORIT_HOST,WAITFORIT_PORT, and others.
Note:
For the case handling arguments in lines 74–75, using array substitution may risk word splitting. Consider refactoring as follows for added robustness:- WAITFORIT_hostport=(${1//:/ }) + IFS=':' read -ra WAITFORIT_hostport <<< "$1"[shellcheck]
🧰 Tools
🪛 Shellcheck (0.10.0)
[warning] 75-75: Quote to prevent word splitting/globbing, or split robustly with mapfile or read -a.
(SC2206)
174-183: Subcommand Execution and Array Expansion CautionBefore executing a subcommand, the script checks if
WAITFORIT_CLIis set. Note that expanding an array without an index (as in the condition on line 174) only evaluates its first element. It is more robust to check the array length as follows:- if [[ $WAITFORIT_CLI != "" ]]; then + if [ ${#WAITFORIT_CLI[@]} -gt 0 ]; thenThen, executing the subcommand using
exec "${WAITFORIT_CLI[@]}"is correct.
[shellcheck]🧰 Tools
🪛 Shellcheck (0.10.0)
[warning] 174-174: Expanding an array without an index only gives the first element.
(SC2128)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
.gitignore(1 hunks)backend/Dockerfile.dev(1 hunks)script/docker-compose-dev.yml(1 hunks)script/setup_and_run.sh(1 hunks)script/wait-for-it.sh(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- .gitignore
🧰 Additional context used
🪛 Shellcheck (0.10.0)
script/setup_and_run.sh
[warning] 10-10: JAR_FILE appears unused. Verify use (or export if used externally).
(SC2034)
script/wait-for-it.sh
[warning] 61-61: Use single quotes, otherwise this expands now rather than when signalled.
(SC2064)
[warning] 75-75: Quote to prevent word splitting/globbing, or split robustly with mapfile or read -a.
(SC2206)
[error] 153-153: This redirection overrides the output pipe. Use 'tee' to output to both.
(SC2260)
[warning] 174-174: Expanding an array without an index only gives the first element.
(SC2128)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: Send PR Notification to Reviewers
🔇 Additional comments (12)
backend/Dockerfile.dev (2)
1-9: Base Image and Build SetupThe Dockerfile correctly starts with
amazoncorretto:17and sets up the build context using an argument for the JAR file, working directory, and file copies. Ensure that the build context (especially the JAR file location and thescript/wait-for-it.shrelative path) is correct when running the build.
10-11: ENTRYPOINT and Service Readiness HandlingThe ENTRYPOINT command leverages the
wait-for-it.shscript to pause container start-up until the database atdb:3306is ready. Consider adding anEXPOSE 8080instruction to document the service port if desired.script/docker-compose-dev.yml (2)
1-17: Database Service ConfigurationThe MySQL service is well configured for a development environment with proper environment variables, port mapping (exposing container port 3306 externally as 3307), character-set, and collation settings. For production, consider externalizing credentials.
18-30: API Service Configuration and DependencyThe API service correctly depends on the
dbservice and sets the JDBC URL along with other environment variables for database connectivity. This clear separation fosters reliable inter-service communication. Ensure that any sensitive credentials are managed securely for production.script/setup_and_run.sh (4)
1-12: Environment Setup and Variable DefinitionsDirectory paths and variable definitions (such as
IMAGE_NAME,IMAGE_TAG,JAR_FILE, andDOCKERFILE) are clear and help manage the build context effectively.🧰 Tools
🪛 Shellcheck (0.10.0)
[warning] 10-10: JAR_FILE appears unused. Verify use (or export if used externally).
(SC2034)
13-19: Gradle Build Process ExecutionThe script properly ensures the Gradle wrapper is executable and then invokes a clean build. This guarantees that the latest code is compiled before Docker image construction.
28-29: Returning to the Original Script DirectoryChanging back to the original directory before executing Docker Compose is a good practice to avoid path confusion.
45-46: Executing Docker ComposeThe final Docker Compose command starts the backend API and MySQL containers in detached mode, and a confirmation message is clearly logged.
script/wait-for-it.sh (4)
1-7: Script Initialization and Utility FunctionsThe shebang (
#!/usr/bin/env bash) and initial helper functions (echoerrandusage) are implemented correctly and provide clear error handling and usage messaging.
25-49: Efficient Wait Function ImplementationThe
wait_forfunction correctly implements a connection check using eithernc(netcat) or a direct TCP connection attempt via/dev/tcp. Timing information logged via timestamps aids in debugging wait durations.
139-143: Default Value AssignmentThe use of default values for
WAITFORIT_TIMEOUT,WAITFORIT_STRICT, andWAITFORIT_QUIETensures that the script behaves predictably even if optional arguments are not provided.
160-171: Child Process and Wait LogicThe conditional handling for when the script runs as a child process versus as the main process is structured clearly, ensuring that the wait is performed correctly and the script exits with the appropriate code.
| echo "${IMAGE_NAME}/${IMAGE_TAG} 이미지를 빌드 중..." | ||
|
|
||
| docker build --build-arg --no-cache -f "${DOCKERFILE}" -t "${IMAGE_NAME}:${IMAGE_TAG}" "${BASE_DIR}" | ||
|
|
||
| echo "도커 이미지 빌드 완료" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
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.
| 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 "도커 이미지 빌드 완료" |
| 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 | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| 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)
| 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| 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)
efdao
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
고생하셨습니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
backend/Dockerfile.dev (1)
12-12: Configuring the Entry Point
TheENTRYPOINTis set to run thewait-for-it.shscript which blocks until the database atdb:3306becomes available before launching the Java application with the specified Spring profile and timezone settings. For increased flexibility in different deployment environments, consider making the database host and port configurable via environment variables.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
backend/Dockerfile.dev(1 hunks)
🔇 Additional comments (7)
backend/Dockerfile.dev (7)
1-1: Base Image Selection
The base imageamazoncorretto:17-alpineis a good choice for a lightweight Java environment. For reproducible builds, consider further pinning the image if necessary.
3-3: Parameterized JAR File Path
Using theARGinstruction forJAR_FILEenables flexible configuration at build time, which is especially useful when the build artifact location may change.
4-4: Bash Installation
The use ofapk add --no-cache bashis appropriate to ensure the container has Bash installed, with the--no-cacheoption keeping the image lean.
6-6: Working Directory Setup
Setting the working directory withWORKDIR /appis a best practice that ensures all subsequent commands execute in the correct directory.
8-8: Copying Application JAR
Copying the JAR file using the build argument${JAR_FILE}and renaming it toapp.jaris flexible. Please verify that the intended JAR file exists in the build context when executing the build.
9-9: Copying Wait-for-it Script
Copying thewait-for-it.shscript into/app/config/ensures the necessary script is available within the container. Double-check the relative path from your Docker build context to avoid path issues.
10-10: Granting Execution Permissions
Applyingchmod +xto/app/config/wait-for-it.shguarantees that the script will run as intended during container startup.
#️⃣ 연관된 이슈>
📝 작업 내용> 이번 PR에서 작업한 내용을 간략히 설명해주세요(이미지 첨부 가능)
로컬에서 백엔드 api 테스트를 할 수 있는 환경을 만들었습니다.
🙏 여기는 꼭 봐주세요! > 리뷰어가 특별히 봐주었으면 하는 부분이 있다면 작성해주세요
Summary by CodeRabbit
Chores
New Features