포트포워딩하기

docker run -d #detach의 약자로 백그라운드에서 작동하도록 하는 옵션 (daemon으로 외워도 될듯하다)
docker run -p #port를 지정해주는 옵션으로 "HOST:CONTAINER" 형식으로 나열
docker run -d -p 8080:80 httpd #호스트의 8080으로 접근하면 컨테이너 80포트로 전달해준다

 

현재 나의 구성도

[인터넷] - KT공유기 - DMZ - IPTIME공유기 - H2서버

 

Apache 컨테이너 실행하기

docker run -d -p 9096:80 httpd

이제 호스트OS로 9096으로 요청하면 아파치 컨테이너의 80포트로 연결해주게 된다.

원격지에서 실험해보니 정말 잘동작한다.

원격지:9096 ▶ 인터넷 ▶ KT공유기 ▶ DMZ ▶ IPTIME공유기 ▶ 9096포트를 H2:9096으로포트포워딩 
▶ H2서버9096 ▶ httpd컨테이너

이렇게 되어있는 건데 iptime공유기에서 외부의 9096을 내부의 9096으로 설정해놔서 가능하다.

KT공유기와 iptime공유기는 DMZ설정이 되어있어서 모든 요청을 IPTIME공유기로 통과하도록 설정해놨다.

 

Apache 컨테이너 실행하기

docker run -d -p 9096:80 httpd

이제 호스트OS로 9096으로 요청하면 아파치 컨테이너의 80포트로 연결해주게 된다.

 

Nginx 컨테이너 실행하기

docker run -d -p 9097:80 nginx

apache나 nginx나 같은 80포트를 사용하지만 HostOS에서 포트포워딩을 해주니까 상관없다는 점이 정말 좋은거 같다.

9096으로 접근하면 httpd 80

9097로 접근하면 nginx 80

 

 

※ docker run을 할 때 로컬에 저장되지 않은 이미지를 지정하면 도커허브에서 자동으로 pull해서 run을 해준다.
즉, docker run nginx를 하였을 때, 로컬에 nginx이미지가 있으면 있는것을 사용하고 없으면 자동으로 도커허브에서 다운로드받아서 run해준다.

 

 

 

 

 

 

 

 

 

컨테이너 특징(생명주기 관련)

컨테이너 내부에 프로그램이 일회성 이라면 컨테이너를 띄우자마자 종료되어버린다.

즉, 컨테이너에서 실행될 프로그램이 데몬처럼 백그라운드에 떠있으며 무언가를 처리하는 종류가 아니라 어떤 일을 끝마치고 종료되는 프로그램이라면 컨테이너도 그 프로그램이 종료되면 같이 종료되어버린다고 한다.

 

명령어

이미지 다운로드 (테스트를 위해 tomcat)

docker pull tomcat

컨테이너 실행하기

docker run tomcat # 포그라운드로 컨테이너가 실행된다.

 

컨테이너 백그라운드로 실행하기

일반적으로 docker run tomcat같은 명령어로 실행하면 컨테이너가 포그라운드로 실행되어 해당 터미널에서는 어떤한 작업도 할 수 없게 된다. (또한 해당 터미널 접속이 끊어지면 실행중이던 컨테이너도 중지되므로 매우 불편하다.) 그래서 대부분 컨테이너를 실행할 때는 백그라운드 모드로 실행한다.

docker run -d [IMAGE ID]

 

컨테이너가 정상적으로 실행되고 있는지 확인하기 (실행중인 컨테이너, 중지된 컨테이너 두 개다 확인하는 방법)

docker ps #현재 실행중인 컨테이너 확인
docker ps -a #실행중이거나 중지된 컨테이너까지 모두 확인

컨테이너를 중지시키는 방법

docker stop [CONTAINER ID]

도커에서 실행중인 톰캣으로 접근이 안되는 이유

도커에 톰캣을 띄워놓고 호스트OS나 다른 곳에서 localhost:8080 을 해도 도커에 실행중인 톰캣에 접근이 안되는 이유는 도커와 호스트OS는 다른 네트워크 대역을 사용하고 있기 때문이다.

만약에 도커에 있는 톰캣으로 접근하고 싶다면 호스트OS에서 도커로 접근하는 요청에 대해 포트포워딩을 해줘야 한다.

 

가위바위보에서 굳이 useEffect나 componentDidMount 에서만 setInterval을 사용하는건 아니고, 필요할 때 setInterval을 쓰고 componentWillUnMount에서 정리만 잘하면 된다.

 

Hooks는 함수 컴포넌트를 말하는 것이 아니라 useEffect, useState 같은 것들을 말하는 것이다.

 

Lotto.jsx (내가 만든 코드 + 강의코드)

import React, {Component} from "react";
import Ball from "./Ball";

const winBall = () => {
    const balls = Array(45).fill(0).map((v,i) => i+1);
    const result = [];
    while(balls.length > 0){
        const randIndex = Math.floor(Math.random() * balls.length); // <= 0 x < length
        result.push(balls.splice(randIndex, 1)[0]);
    }
    const bonus = result[result.length - 1]; //맨 마지막
    const wins = result.slice(0,6).sort((a,b)=>a-b); // 0~5
    console.log(wins, bonus);
    return [...wins, bonus];
}

class Lotto extends Component{
    state = {
        winNumbers: winBall(),
        winBalls:[],
        bonus:null,
        redo:false,
    }
    timeouts=[];

    componentDidMount() {
        console.log('componentDidMount')
        this.startLotto();
    }

    onClickRedo = () => {
        this.setState({
            winNumbers: winBall(),
            winBalls:[],
            bonus:null,
            redo:false
        });
        this.timeouts = [];
    }

    componentDidUpdate(prevProps, prevState, snapshot) {
        if(this.state.winBalls.length === 0){
            this.startLotto();
        }
    }

    componentWillUnmount() {
        this.timeouts.forEach(v => clearTimeout(v));
    }

    startLotto = () => {
        const length = this.state.winNumbers.length - 1;
        for(let i=0; i<length; i++){
            const timerId = setTimeout(()=>{
                this.setState((prev)=>{
                    const winBall = prev.winNumbers.slice(i,i+1)[0];

                    return {
                        winNumbers:[...prev.winNumbers],
                        winBalls:[...prev.winBalls, winBall],
                        bonus:null,
                        redo:false
                    }
                });
            },1000 * (i+1));
            this.timeouts.push(timerId);
        }

        this.timeouts[6] = setTimeout(()=>{
            this.setState({bonus: this.state.winNumbers[length],redo:true});
        }, 1000 * this.state.winNumbers.length);
    }

    render() {
        const {winNumbers, winBalls, bonus, redo} = this.state;
        return (
            <>
                {winBalls.map(v=><Ball number={v} key={v+1}/>)}

                {
                    bonus && <><div className="bonus__comment">보너스!</div><Ball number={bonus} /></>
                }
                {
                    redo && <button onClick={this.onClickRedo}>한번더!</button>
                }
            </>
        )
    }
}

export default Lotto;

 

 

Ball.jsx

import React, {memo} from 'react';
const Ball = memo(({number})=>{
    let background, color = null;
    if(number >= 40){
        background = 'red';
    }else if(number >= 30){
        background = 'green';
    }else if(number >= 20){
        background = 'yellow';
    }else if(number >= 10){
        background = 'blue';
        color = 'white';
    }else{
        background = 'aqua';
    }

    return (
        <>
            <div className="ball" style={{background, color}}>
                {number}
            </div>
        </>
    )
});

export default Ball;

 

 

LottoHooks.jsx

import React, {useEffect, useRef, useState} from "react";
import Ball from "./Ball";

const LottoHooks = () => {
    const winBall = () => {
        const balls = Array(45).fill(0).map((v,i) => i+1);
        const result = [];
        while(balls.length > 0){
            const randIndex = Math.floor(Math.random() * balls.length); // <= 0 x < length
            result.push(balls.splice(randIndex, 1)[0]);
        }
        const bonus = result[result.length - 1]; //맨 마지막
        const wins = result.slice(0,6).sort((a,b)=>a-b); // 0~5
        console.log(wins, bonus);
        return [...wins, bonus];
    }

    const [winNumbers, setWinNumbers] = useState(winBall);
    const [winBalls, setWinBalls] = useState([]);
    const [bonus, setBonus] = useState(null);
    const [redo,setRedo] = useState(false);
    const timerRef = useRef([]);


    useEffect(()=>{
        for(let i=0; i<6; i++){
            const timerId = setTimeout(()=>{
                setWinBalls((prev)=>{
                    return [...prev, winNumbers[i]];
                });
            },(i+1) * 1000);
            timerRef.current.push(timerId);
        }
        timerRef.current[6] = setTimeout(()=>{
            setBonus(winNumbers[6]);
            setRedo(true);
        },7000);
    },[winNumbers]);

    const onClickRedo = (param) => (e) => {
        console.log(param);
        console.log(e.target);
        setWinBalls([]);
        setWinNumbers(winBall);
        setBonus(null);
        setRedo(false);
        timerRef.current = [];
    }

    return (
        <>
            {
                winBalls.map((v,i) => <Ball number={v} key={v+i}/>)
            }
            {
                bonus && <><div>보너스!!</div><Ball number={bonus} /></>
            }
            {
                redo && <button onClick={onClickRedo(1)}>한번더</button>
            }
        </>
    );
}

export default LottoHooks;

+ Recent posts