묻고 답해요
164만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨비전공자도 이해할 수 있는 Docker 입문/실전
depends_on에 따른 컨테이너 실행 순서
services: my-server: build: . ports: - 8080:8080 depends_on: my-db: condition: service_healthy my-db: image: mysql environment: MYSQL_ROOT_PASSWORD: pwd1234 MYSQL_DATABASE: mydb volumes: - ./mysql_data:/var/lib/mysql ports: - 3306:3306 healthcheck: test: ["CMD", "mysqladmin", "ping"] interval: 5s retries: 10강의 자료대로 이렇게 작성했는데이렇게 설정하면 my-db가 healthy할 때 my-server 컨테이너를 실행한다고 이해했습니다.그런데 docker compsoe logs로 확인해 보면 my-server가 먼저 실행되고, 중간에 대기하는 거 같은데, 저는 애초에 my-server 컨테이너 실행이 늦춰지는 거라 생각했었거든요.healthcheck와 depends_on이 정확히 어떻게 동작하는 건가요?
-
미해결비전공자도 이해할 수 있는 Docker 입문/실전
실제 웹 서비스 배포 시 질문
안녕하세요 강사님! 저는 프론트엔드 개발자이고 현재 진행중인 사이드 프로젝트에서 Docker, AWS를 사용해서 Next.js 프로젝트를 배포하려고 합니다.머릿속으로 큰 그림을 그려봤을때, 강의에서 나오는 컨테이너 역할을 해주는 게 AWS EC2이고 https의 기본 포트는 443번이니까 실제 배포할때는 docker run -d -p 443:3000 my-web-server 이런식으로 포트가 맵핑돼야한다고 이해하고 있는데 제가 올바르게 이해하고 있는 게 맞을까요? 추가로 현재는 로컬에서 직접 docker run -d -p 80:3000 my-web-server를 실행하는데, 배포하게 된다면 이 명령어를 누가 실행시켜주는지도 궁금합니다..!
-
해결됨개발자를 위한 쉬운 도커
vscode 터미널 설정 관련 질문
안녕하세요vscode 설치하고 나서 기본프로필설정 하면 git-bash 가 보이질 않습니다.어떻게 하면 될까요?
-
미해결비전공자도 이해할 수 있는 Docker 입문/실전
도커 volume 질문
안녕하세요,1.도커 이미지를 이서버 , 저서버 왔다가 하는 경우면도커 컨테이너?이미지? 안에 있는 volume에 db를 저장해놓는게 좋죠??(호스트 storage를 이용해 db를 저장할 수도 있다고 하셔서 질문 드립니다) 도커 컨테이너 volume 저장 공간은 원하는 만큼 조정 할 수 있나요 (최대 호스트 디스크 저장공간)?도커 사용이 처음이라 질문이 모호한점 양해 부탁드립니다..
-
해결됨비전공자도 이해할 수 있는 Docker 입문/실전
HTTPS로도 받고 싶으면 docker compose에 443도 쓰면 될까요?
services: my-web-server: build: . ports: - 80:3000이게 자료 예시인데 HTTPS도 받으려면 ports 부분에 - 443:3000도 써 주면 되는 건가요?현업에선 어떤 식으로 하나요?
-
미해결비전공자도 이해할 수 있는 Docker 입문/실전
sql 볼륨 폴더 지우면 데이터베이스 데이터 날라가는거 아닌가요?
mysql_data 폴더 지우고 다시 폴더 만들면 데이터베이스 안에 있는 데이터가 다 날라가는거 아닌가요? 그럼 볼륨을 사용하는 이유가 없을거 같아서요
-
미해결비전공자도 이해할 수 있는 Docker 입문/실전
39강 도커파일 빌드 경로 질문이 있습니다.
[01:57] 에 상대경로로 .을 찍으라고 돼있는데요.그냥 절대경로 쓰는게 더 낫지 않나요?절대경로로도 동작하는데, 귀찮게 디렉토리 이동해야 하는 상대경로를 쓰는 이유가 궁금합니다.혹시 나중에 자동화할때 상대경로를 써야한다든지 등의 실무적인 이유가 있을까요?제가 모르는 큰 그림이 있는지 궁금합니다.
-
미해결비전공자도 이해할 수 있는 Docker 입문/실전
도커파일 copy
폴더 복사가 안되서요. 여러번 해봤는데 이미지 새로 생성 안하면 변경이 안되나봐요. 새로 생성한 이미지로 해보면 my-app 이 생성됩니다.
-
해결됨비전공자도 이해할 수 있는 Docker 입문/실전
실무에서 docker compose up --build를 할 때
docker compose up --build 같은 명령어는 실무에서 보통기존 컨테이너를 중지한 다음에 하는 건가요? 아니면 실행 중인 상태에서 바로 저 명령어를 쓰는 편인가요?상관없나요?
-
해결됨K6로 배우는 Spring Boot 부하 테스트 입문
그라파나 화면 관련하여 궁금한게 있습니다.
현재 화면에는 p90, p95만 있는데 p99도 보고 싶으면 어떻게 해야하나요?
-
해결됨K6로 배우는 Spring Boot 부하 테스트 입문
그라파나에 뜨는 화면 관련해서 질문 있습니다
localhost:3000 띄우고 강의에서 시키는 대로 한 후 grafana 화면 들어가니 전부 NA 만뜨고 한번은 우측 상단에 Unexpected Error 라는 문장이 뜬적이 있는데 왜 그런가요?
-
해결됨비전공자도 이해할 수 있는 Docker 입문/실전
mysql_data 폴더 내부에 다른 파일이 있는데도 잘 되는 경우
docker run -e MYSQL_ROOT_PASSWORD=password123 -p 3306:3306 -v /Users/jaeseong/Documents/Develop/docker-mysql/mysql_data:/var/lib/mysql -d mysql 이 명령을 하기 전에 mysql_data 폴더는 만들어 놔도 되지만, 폴더 내부에 다른 파일이 있으면 안 된다고 이해했습니다. 그런데 바로 이전 '[실습] Docker로 MySQL 실행시켜보기 - 3 강의' https://jscode.notion.site/Docker-MySQL-3-f07a2d5a24d24bf184e78622e55a6d8c에서 비밀번호 바꿔 보는 테스트를 할 때, password123으로 컨테이너를 실행한 뒤, 컨테이너를 삭제한 후 mysql_data 폴더는 따로 삭제하지 않아서 mysql_data 내부엔 파일들이 있었을 텐데, 그 이후에 pwd1234로 바꿔서 컨테이너를 다시 생성할 때 오류가 안 났던 이유는 뭔가요?
-
해결됨비전공자도 이해할 수 있는 Docker 입문/실전
도커 허브에서 postgres 버전 확인하는 법
도커 허브에 있는 postgres:latest인데https://hub.docker.com/layers/library/postgres/latest/images/sha256-c84595a367a3fe5a4d9dce011490da38c462190e6ac7afb7d2a4c49436c80656 이건 postgres 몇 버전인가요? 다른 Q&A 보니 postgres 버전 관련 얘기가 있어서 최신 postgres가 18버전인지, 그 이상이 나왔는지 보고 싶었는데 저 링크를 들어가도 어디서 확인해야 하는지 모르겠습니다. 그리고 newest는https://hub.docker.com/layers/library/postgres/14.20-alpine3.23/images/sha256-df852d122662b3a4ef0662daf3572ec3f6251924fbd2e44bc5d9d8ed252ae767 postgres:14.20-alpine3.23인데, 이건 14 버전인가요? postgres 18버전도 나온 거로 알아서 14라는 게 버전은 아닌 거 같은데, 어디서 버전을 확인할 수 있는지 궁금합니다.
-
해결됨비전공자도 이해할 수 있는 Docker 입문/실전
보충 자료와도 관련된 추가 내용
"[보충 자료] Docker로 PostgreSQL 실행시켜보기"에 관련 내용이 있기는 한데, 제가 이걸 못 보고 /var/lib/postgresql/data라고 썼다가 제대로 작동이 안 돼서 GPT에 물어보면서 해결했습니다. /var/lib/postgresql/data를 /var/lib/postgresql 이렇게만 바꿔도 오류는 발생하지 않는 것 같습니다. 보충 자료에 나온 것처럼 /var/lib/postgresql/<버전>/docker로 쓰는 거랑 완전히 같은 게 맞는지 확신은 안 되지만 강의 따라하면서 문제는 없었습니다. docker run -d -e POSTGRES_PASSWORD=password123 -p 5432:5432 -v D:\docker-postgresql/postgresql_data:/var/lib/postgresql postgres 위 명령어를 입력하면, 데이터들이 있는 호스트 디렉터리 주소는 아래와 같은 구조가 됩니다.
-
해결됨비전공자도 이해할 수 있는 Docker 입문/실전
현업에서 MySQL은 RDS와 도커 볼륨 중 어떤 걸 사용하나요?
아니면 MySQL을 사용할 때 도커와 RDS를 조합해서 사용할 수도 있나요? 현업에서 어떤 식으로 사용하는지 궁금합니다.
-
해결됨토스 개발자와 함께하는 Data Workflow Management 기반의 대용량 데이터 처리 설계 패턴
강의에서사용하신 root.py 파일이 안보여서 실습하면서 만든 텍스트 공유 드려요
dynamicDagfrom datetime import datetime, timedelta from airflow import DAG from airflow.operators.python import PythonOperator from db_utils import execute_query import logging def log_task_start(message): logging.info(f"[START] {message}") def log_task_end(message): logging.info(f"[END] {message}") # 분석할 주식 종목 리스트 (설정으로 관리) STOCK_SYMBOLS = ['AAPL','GOOGL','MSFT','AMZN','TSLA'] default_args = { 'owner': 'data-team', 'depends_on_past': False, 'start_date': datetime(2024, 1, 1), 'email_on_failure': False, 'email_on_retry': False, 'retries': 1, 'retry_delay': timedelta(minutes=5), } def analyze_stock_data(symbol, **context): """주식 종목에 대해서, 최근 30일간의 주식 데이터를 분석""" log_task_start(f"주식 분석 - {symbol}") query = """ SELECT symbol, AVG(price) as avg_price, MAX(price) as max_price, MIN(price) as min_price, SUM(volume) as total_volume, COUNT(*) as trading_days FROM stock_prices WHERE symbol = %s AND trade_date >= DATE_SUB(CURDATE(), INTERVAL 30 DAY) GROUP BY symbol """ result = execute_query(query, [symbol]) if result: data = result[0] print(f"{symbol} 분석 결과:") print(f" 평균 가격: ${data[1]:.2f}") print(f" 최고 가격: ${data[2]:.2f}") print(f" 최저 가격: ${data[3]:.2f}") print(f" 총 거래량: {data[4]:,}") print(f" 거래일수: {data[5]}일") log_task_end(f"주식 분석 - {symbol}") return result def create_stock_dag(symbol): """개별 주식에 대한 DAG 생성 함수""" dag_id = f'stock_analysis_{symbol.lower()}' dag = DAG( dag_id, default_args=default_args, description=f'{symbol} 주식 데이터 분석 DAG', schedule='@daily', catchup=False, tags=['dynamic', 'stock', 'analysis', symbol] ) # 데이터 품질 체크 태스크 def check_data_quality(**context): query = """ SELECT COUNT(*) as count FROM stock_prices WHERE symbol = %s AND trade_date = CURDATE() - INTERVAL 1 DAY """ result = execute_query(query, [symbol]) logging.info(f"{symbol} 데이터 품질 체크: {result[0][0] if result else 0}") return result data_quality_check = PythonOperator( task_id=f'check_data_quality_{symbol.lower()}', python_callable=check_data_quality, dag=dag ) # 주식 분석 태스크 analyze_task = PythonOperator( task_id=f'analyze_{symbol.lower()}', python_callable=analyze_stock_data, op_kwargs={'symbol': symbol}, dag=dag ) # 결과 저장 태스크 def save_results(**context): query = """ INSERT INTO daily_stats (symbol, summary_date, avg_price, total_volume, trade_count) SELECT %s, CURDATE() - INTERVAL 1 DAY, AVG(price), SUM(volume), COUNT(*) FROM stock_prices WHERE symbol = %s AND trade_date = CURDATE() - INTERVAL 1 DAY ON DUPLICATE KEY UPDATE avg_price = VALUES(avg_price), total_volume = VALUES(total_volume), trade_count = VALUES(trade_count) """ result = execute_query(query, [symbol, symbol]) logging.info(f"{symbol} 분석 결과 저장 완료") return result save_results = PythonOperator( task_id=f'save_analysis_{symbol.lower()}', python_callable=save_results, dag=dag ) # 태스크 의존성 설정 data_quality_check >> analyze_task >> save_results return dag # Dynamic DAG 생성 # 각 주식 종목에 대해 별도의 DAG 생성 for symbol in STOCK_SYMBOLS: dag_id = f'stock_analysis_{symbol.lower()}' globals()[dag_id] = create_stock_dag(symbol)CrossDag (트리거 센서)from datetime import datetime, timedelta from airflow import DAG, Dataset from airflow.operators.python import PythonOperator from airflow.operators.trigger_dagrun import TriggerDagRunOperator from airflow.sensors.external_task import ExternalTaskSensor from db_utils import execute_query import logging #기본 설정 default_args = { 'owner': 'data-team', 'start_date': datetime(2024, 1, 1), 'retries': 1, 'retry_delay': timedelta(minutes=2), } # ======================================================== # TriggerDagRunOperator # ======================================================== def process_data(**context): """간단한 데이터 처리""" logging.info("데이터 처리 시작") query = "SELECT COUNT(*) FROM stock_prices" result = execute_query(query) count = result[0][0] if result else 0 logging.info(f"처리된 레코드 수 : ${count}") return {"record_count": count} trigger_dag = DAG( 'trigger_example_dag', default_args=default_args, description='TriggerDagRunOperator 예제', schedule='@daily', catchup=False, tags=['cross-dag', 'trigger'] ) process_task = PythonOperator( task_id='process_data', python_callable=process_data, dag=trigger_dag ) #다른 DAG를 트리거 (가장 기본적인 사용법) trigger_next_dag = TriggerDagRunOperator( task_id='trigger_sensor_dag', trigger_dag_id='sensor_example_dag', wait_for_completion=False, # 완료를 기다리지 않음 dag=trigger_dag ) process_task >> trigger_next_dag # ======================================================== # ExternalTaskSensor # ======================================================== # 두 번째 DAG: 외부 태스크 대기 def analyze_triggered_data(**context): """트리거된 후 분석 작업""" logging.info("외부 태스크 완료 후 분석 시작") # 간단한분석로직 analysis_result = {"status": "completed", "timestamp": str(datetime.now())} logging.info(f"분석 완료: {analysis_result}") return analysis_result sensor_dag = DAG( 'sensor_example_dag', default_args=default_args, description='ExternalTaskSensor 예제', schedule=None, # 트리거로만 실행됨 catchup=False, tags=['cross-dag', 'sensor'] ) # 외부 DAG의 태스크 완료를 기다림 def get_most_recent_dag_run(dt): """가장 최근의 DAG 실행을 찾는 함수""" from airflow.models import DagRun from airflow.utils.session import provide_session @provide_session def get_recent_run(session=None): recent_run = session.query(DagRun).filter( DagRun.dag_id == 'trigger_example_dag', DagRun.state == 'success' ).order_by(DagRun.execution_date.desc()).first() if recent_run: return recent_run.execution_date return dt return get_recent_run() wait_for_external_task = ExternalTaskSensor( task_id='wait_for_process_data', external_dag_id='trigger_example_dag', # 기다릴 DAG external_task_id='process_data', # 기다릴 태스크 execution_date_fn=get_most_recent_dag_run, #최근성공한 실행 DAG timeout=60, # 1분 타임아웃 poke_interval=5, # 5초마다 확인 allowed_states=['success'], #성공 상태만 기다림 dag=sensor_dag ) analyze_task = PythonOperator( task_id='analyze_triggered_data', python_callable=analyze_triggered_data, dag=sensor_dag ) wait_for_external_task >> analyze_task # ======================================================== # Dataset Denpendencies # ======================================================== # Dataset 정의 (Dataset Dependencies 용) market_data_dataset = Dataset("market_data") analysis_dataset = Dataset("analysis_result") def create_market_data(**context): """마켓 데이터를 생성하고 Dataset을 업데이트""" logging.info("마켓 데이터 생성 시작") # 실제 데이터 생성 로직 query = """ SELECT symbol, AVG(price) as avg_price FROM stock_prices WHERE trade_date = CURDATE() - INTERVAL 1 DAY GROUP BY symbol LIMIT 3 """ result = execute_query(query) market_data = [] if result: for row in result: market_data.append({"symbol": row[0], "avg_price": float(row[1])}) logging.info(f"생성된 마켓 데이터: {market_data}") return market_data dataset_producer_dag = DAG( 'dataset_producer_dag', default_args=default_args, description='Dataset Dependencies - 생산자', schedule='@daily', catchup=False, tags=['cross-dag', 'dataset', 'producer'] ) create_data_task = PythonOperator( task_id='create_market_data', python_callable=create_market_data, outlets=[market_data_dataset], # Dataset 업데이트 알림 dag=dataset_producer_dag ) # Consumer def consume_market_data(**context): """생성된 마켓 데이터를 소비하여 분석""" logging.info("마켓 데이터 소비 및 분석 시작") # Dataset이 업데이트되면 자동으로 실행됨 query = "SELECT COUNT(DISTINCT symbol) FROM stock_prices" result = execute_query(query) symbol_count = result[0][0] if result else 0 analysis = { "total_symbols": symbol_count, "analysis_time": str(datetime.now()), "status": "Dataset 기반 분석 완료" } logging.info(f"Dataset 기반 분석 결과: {analysis}") return analysis def generate_final_report(**context): """최종 리포트 생성""" logging.info("최종 리포트 생성") ti = context['ti'] analysis = ti.xcom_pull(task_ids='consume_market_data') report = f"Dataset 기반 리포트: {analysis.get('total_symbols', 0)}개 심볼 분석 완료" logging.info(report) return report dataset_consumer_dag = DAG( 'dataset_consumer_dag', default_args=default_args, description='Dataset Dependencies - 소비자', schedule=[market_data_dataset], # Dataset이 업데이트되면 실행 catchup=False, tags=['cross-dag', 'dataset', 'consumer'] ) consume_task = PythonOperator( task_id='consume_market_data', python_callable=consume_market_data, outlets=[analysis_dataset], # 다음 Dataset 업데이트 dag=dataset_consumer_dag ) report_task = PythonOperator( task_id='generate_final_report', python_callable=generate_final_report, dag=dataset_consumer_dag ) consume_task >> report_task
-
해결됨비전공자도 이해할 수 있는 Docker 입문/실전
노션 자료에 안 보이는 이미지가 있습니다
'[보충 자료] Windows에서 lsof, kill, sudo 명령어가 작동하지 않을 때 대처 방법'여기서 관리자 권한으로 실행 부분 이미지가 저렇게 보입니다.
-
해결됨비전공자도 이해할 수 있는 Docker 입문/실전
도커 허브에서의 latest가 가장 최신인 게 맞나요?
newest로 정렬했을 때 가장 최신인 건 trixie-perl이니 이게 latest여야 하지 않나 생각이 되는데 왜 latest가 따로 있는 건지 궁금합니다. 용량이 다른 걸 보니 다른 이미지 같은데, 최신으로 올라온 게 latest여야 하지 않나요? 어떤 이유인지 궁금합니다.
-
해결됨개발자를 위한 쉬운 도커
쿠버네티스 강의 언제 나오나요..
11월 초에 나온다고 하셔서 기다리고 있습니다.아직 완강하지 않았더라도 연재식으로라도 강의 올려주셨으면 좋겠어요
-
해결됨비전공자도 이해할 수 있는 Docker 입문/실전
docker image ls 실행 시 나오는 내용이 다릅니다
윈도우의 Powershell 관리자 모드에서 실행했습니다.강의를 보기 전에 노션 학습 자료 먼저 예습하고 있었는데, docker image ls를 제가 실행해 보니 전혀 다른 내용으로 출력됩니다. 이건 운영체제 차이인가요 아니면 최근에 바뀐 건가요?