묻고 답해요
164만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨비전공자도 이해할 수 있는 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를 제가 실행해 보니 전혀 다른 내용으로 출력됩니다. 이건 운영체제 차이인가요 아니면 최근에 바뀐 건가요?
-
미해결비전공자도 이해할 수 있는 Docker 입문/실전
윈도우 볼륨 생성이 안됩니다.
윈도우(Windows) 환경으로 실습하시는 수강생분들 중에서볼륨이 제대로 생성되지 않는 분들은 아래 링크의 해결책을 참고해보세요!https://inf.run/7d8pW위 링크에 나와있는 방식대로 해결이 안 되실 경우 질문 게시판에 질문 남겨주시기 바랍니다:D위에 방법으로 더블 쿼터로 묶어도 해당 문제가 해결되지 않습니다.볼륨을 직접 생성해서 하는건 가능하지만, 해당방법으로도 해보고 싶은데 방법은 없는건가요?
-
미해결비전공자도 이해할 수 있는 Docker 입문/실전
섹션 4 FROM : 베이스 이미지 생성 openjdk:17-jdk not found
차례대로 따라가던 중 docker build -t my-jdk17-server . 를 실행하면 ERROR: failed to build: failed to solve: openjdk:17-jdk: failed to resolve source metadata for docker.io/library/openjdk:17-jdk: docker.io/library/openjdk:17-jdk: not found위와 같은 에러가 발생합니다. 이유를 찾아보니 Docker hub 정책변화로openjdk 이미지를 eclipse-temurin 으로 이전한 상태라고 하는데 어떻게 해야하나요?
-
미해결비전공자도 이해할 수 있는 Docker 입문/실전
docker 최신 버전 PGDATA 경로 설정 업데이트 소식 공유
강의에서 말씀하신 것처럼, postgres라고만 입력하면 최신 버전의 PostgreSQL이 실행됩니다.PostgreSQL 18 버전 이상부터는 데이터 디렉터리 경로가 기존의 /var/lib/postgresql/data에서/var/lib/postgresql/<버전>/docker 형태로 변경되었습니다.따라서 저는 현재 최신 버전인 PostgreSQL 18을 사용하고 있어서/var/lib/postgresql/18/docker 경로로 지정해야 오류가 발생하지 않았습니다.만약 PostgreSQL 17 이하 버전을 사용하신다면,강사님께서 안내해주신 기존 경로(/var/lib/postgresql/data)를 그대로 사용하시면 됩니다.아래 링크를 한 번 읽어보시면 도움이 될 것 같습니다.https://forums.docker.com/t/mysterious-docker-issue-with-postgres/149898/7https://github.com/docker-library/postgres/pull/1259
-
해결됨K6로 배우는 Spring Boot 부하 테스트 입문
인프럭스에 데이터는 누가 넣는지
인프럭스에 데이터는 누가 넣는지?
-
미해결비전공자도 이해할 수 있는 Docker 입문/실전
ec2 우분투 도커 설치 관련
안녕하세요 강사님좋은 강의 잘 듣고 있습니다이번 강의를 우분투 환경에서 진행해와서 도커 설치를 이미 했던 것처럼 공식 문서를 통해 다음과 같이 명령어를 작성하려고 했습니다.sudo apt-get update sudo apt-get install ca-certificates curl sudo install -m 0755 -d /etc/apt/keyrings sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc sudo chmod a+r /etc/apt/keyrings/docker.asc echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \ $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt-get update sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin하지만 강의를 따라오다보니 강사님께서 입력하신 명령어가 많이 달라 궁금한 부분이 생겼습니다sudo apt-get update && \ sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common && \ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - && \ sudo apt-key fingerprint 0EBFCD88 && \ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" && \ sudo apt-get update && \ sudo apt-get install -y docker-ce && \ sudo usermod -aG docker ubuntu && \ newgrp docker && \ sudo curl -L "https://github.com/docker/compose/releases/download/2.27.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose && \ sudo chmod +x /usr/local/bin/docker-compose && \ sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose명령어를 천천히 살펴보다가 몇 가지 궁금한 게 생겨서 질문드립니다공식 문서로 할때는 -o로 직접 저장을 했는데 강사님이 써주신 방식이 어떤 방식의 이점이 있는지, 실제로 업무에서 사용할 땐 아래 방식으로 써야하는지 궁금합니다sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asccurl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - && \ sudo apt-key fingerprint 0EBFCD88 && 공식 문서 명령어를 사용할 때에는 compose나 docker ce 등을 간단하게 한번에 설치했습니다. 강사님 명령어를 살펴보니 다른 방식으로 github에서 받아오시는것 같고 추가적인 명령어도 더 들어가는데 어떤 장점 때문에 이 방식을 쓰시는지 궁금합니다감사합니다
-
해결됨개발자를 위한 쉬운 도커
postgresql-repmgr:15 지원 종료에 따른 대체 이미지 변경 질문드립니다!
안녕하세요, 이중화 DB 구성 파트 강의를 들으면서 실습을 진행하던 중 bitnami/postgresql-repmgr:15 이미지가 없어서 아래 이미지처럼 오류가 발생 중입니다.찾아보니 해당 이미지가 "더 이상 무료로 제공되지 않는다.", "Helm 차트에서 postgresql-ha를 설치해야 한다." 라고 나오더라구요.혹시 이를 대체할 이미지는 어떤 걸로 변경할 수 있는지 궁금합니다!
-
해결됨개발자를 위한 쉬운 도커
섹션 9. 레이어 관리에서 alpine OS 사용 관련 질문 있습니다!
안녕하세요! 섹션 9에 레이어 관리 파트 강의를 듣다가 궁금증이 생겨서 질문드립니다!이미지 크기를 줄이기 위해 최소한의 환경만 갖춰진(?) alpine OS를 사용한다고 이해했습니다.그러면 현업에서는 alpine OS를 사용한다고 가정할 때 해당 OS에 애플리케이션 실행에 필요한 구성이 전부 존재하는지, 어떤 프로그램들을 추가로 설치해야 하는지 확인하는 방법이 있는지 궁금합니다!
-
해결됨개발자를 위한 쉬운 도커
도커 가상 네트워크와 Stateless 특징 관련 질문
안녕하세요!처음 도커를 공부하는데 강의 너무 잘 듣고 있습니다.😀도커 가상 네트워크와 컨테이너 상태 부분을 들으면서 2가지 궁금한게 있어 질문 드립니다. 1.지금까지 스프링부트 애플리케이션을 개발하면서는 DB 접속 도메인을 고정으로 사용해도 되는 경우가 대부분이었는데, (로컬에서 h2 DB 사용 또는 aws rds 처럼 이미 도메인이 부여된 경우) 이런 백엔드 애플리케이션과 프론트엔드 애플리케이션을 같이 띄울때는 도커 dns 기능이 딱히 필요가 없어 보이는데 이런 경우에도 별도로 네트워크를 구성해서 띄우는게 좋을까요? 그냥 기본 bridge 네트워크를 사용하면 될까요?도커 가상 네트워크가 단지 dns 기능만을 위해서 사용되는건지, 하나의 애플리케이션에 필요한 서버 전체 구성을 묶어 주는 개념으로도 사용하는 것인지 궁금합니다. 2. 컨테이너의 Stateless 특징 중에“특정 컨테이너에 쌓인 파일들이 컨테이너의 동작에 영향을 주지 않기 때문에 서버를 지우고 다시 생성하거나 필요하지 않은 서버를 제거할 때 걱정 없이 제거 가능하다” 는 부분이 조금 모호하게 이해됩니다.이미지와 컨테이너를 사용하지 않더라도 서버의 변경 사항을 수정하고 재기동을 하면 이전 서버의 상태와 상관 없이 새로운 내용이 적용되는데, 어떤 차이점이 있는걸까요?여러대의 서버를 사용하는 환경에서 컨테이너를 사용하면 여러대의 서버가 동일한 상태를 가질 수 있다는것이 핵심인 것으로 이해하면 되는 내용인지 헷갈려서 질문 드립니다. 감사합니다 🙇♀
-
해결됨개발자를 위한 쉬운 도커
우분투 설치
안녕하세요.우분투에서 설치 진행하고 싶은데,따로 챕터가 없는 거 같아서요.우분투 셋팅은 어떻게 진행할 수 있을까요?
-
미해결비전공자도 이해할 수 있는 Docker 입문/실전
도커 볼륨 삭제후 복구방법
안녕하세요.좋은 강의 열심히 수강하고 있는 개발자 입니다. 강의를 수강하다 궁금한게 생겨 질문을 남기게 되었습니다. 만약, 실수로 볼륨을 삭제하게 된다면, 볼륨 파일을 다시 복구하는 방법이 있을까요??가령, 데이터베이스의 경우 commit 전이라면 rollback이 가능하듯명령어 실수 혹은 휴먼 에러로 불륨을 삭제하게 되었을시에 대응 방법도 궁금합니다. 감사합니다.
-
미해결비전공자도 이해할 수 있는 Docker 입문/실전
도커 볼륨 관련 질문
Docker로 MySQL을 올리다가 컨테이너가 계속 실패했는데,나중에 보니까 볼륨이 꼬여 있어서 삭제(docker volume prune) 후 해결됐습니다.볼륨이 꽉 차거나 꼬였을 때 컨테이너가 왜 바로 실패하는지,그리고 이런 문제를 실무에서는 어떻게 예방하는지 궁금합니다.
-
해결됨개발자를 위한 쉬운 도커
도커 보안을 실무에서 어떻게 대비하시는지 궁금합니다.
안녕하세요 도커를 사용할 때 보안 이슈는 빼놓을 수 없는 상황입니다. 데몬 기반 구조로 취약점이 있다고 하는데 이론적으로 알겠지만 어떤 원인으로 발생할 수 있고 유사 경험이 있으신지 궁금해요 또 실무 환경에서는 어떤 방식으로 대비를 하고 예방을 하시는지 궁금합니다.