오늘은 저번시간에 실습한 코로나 정보 챗봇 기능에 추가하여 네이버 영화순위 정보를 추가해보겠습니다.

 

앞으로도 모든 실습은 기본 코드에 추가하는 식으로 구현하겠습니다.

 

네이버 영화순위에 나오는 1~5순위 영화 정보를 하나씩 출력하는 식으로 구현할텐데,

한번에 1~5순위 까지 모든 영화정보를 하나의 메시지로 출력하면 최초 영화에 대한 프리뷰 화면만 나오고 

나머지 2~5순위 영화는 영화 이름, 링크만 나오게 되어서 저는 하나의 메시지가 아닌 5개 메세지를 전송받아서 각 영화에 대한 짤막한 정보를 얻게 구현했습니다.

 

아래 링크에서 역시나 F12를 눌러서 우리가 얻어올 영화 이름, 프리뷰, 사진 정보 컴포넌트를 조사합니다.

http://movie.naver.com/movie/running/current.nhn

오른쪽 lst_sdc 클래스를 펼쳐보면 왼쪽 영화 사진/이름/정보 들이 쭉 나열이 되어있습니다.

이 정보를 크롤링하여 각 영화에 대한 정보를 얻어올 수 있습니다.

 

추가한 영화 크롤링 함수입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def movie_chart_crawling():
    session=requests.Session()
    #영화 크롤링 사이트
    addr='http://movie.naver.com/movie/running/current.nhn'
    req=session.get(addr)
    soup=BeautifulSoup(req.text,'html.parser')
    titles=soup.find_all('dl',class_='lst_dsc')
    cnt=1
    output=" "
 
    # 영화제목+ 링크가 순서대로 5개 출력되고 각 영화별 설명이 짤막하게 들어가고 + 출력까지 
    for title in titles:
        output+=str(cnt)+'위: '+title.find('a').text+'\n'+addr+title.find('a')['href']+'\n'
        #여기서 푸쉬해서 5개 각 저옵가 메세지로 출력되게끔
        bot.send_message(chat_id=id,text=output)
        output="" 
        cnt+=1
        if cnt==6:
            break
    #return output 
  
cs

 

추가한 챗봇 송수신 코드입니다.

전에 실습한 코로나 관련 기능 구현은 함수에서 값을 리턴받은 뒤 그 내용을 출력하였지만

이번에는 각 영화에 대한 정보를 하나씩 출력하기 위해 함수 내부에서 크롤링 하고 출력까지 진행하였습니다.

1
2
3
4
5
6
elif(user_text=="영화"):
        bot.send_message(chat_id=id, text="조회 중 입니다...")
        movie_chart=movie_chart_crawling()
        #출력은 위의 함수 내부에서 한다.
        #bot.send_message(chat_id=id,text=movie_chart)
        bot.sendMessage(chat_id=id,text=info_message)
cs

 

결과는 아래와 같습니다. 각 영화정보가 하나의 메세지별로 출력됨을 알 수 있습니다.

 

이번시간부터 본격적으로 본인이 원하는 기능을 서비스받을 수 있는 챗봇을 구현해보겠습니다.

첫 시간이고 앞으로 많은 단계를 거쳐 웹 정보를 크롤링 할 것이므로 패키지들 부터 다 설치해주겠습니다.

저는 vscode에서 python으로 코딩하였습니다. 터미널에서 아래 명령어로 모든 패키지를 설치합니다.

 

pip install python-telegram-bot

pip install telegram

pip install selenium

pip install beautifulsoup4

pip install requests

 

Selenium은 webdriver라는 것을 통해 디바이스에 설치된 브라우저들을 제어할 수 있습니다.

주로 chrome을 많이 사용하므로 chromedriver를 설치합니다.

https://sites.google.com/a/chromium.org/chromedriver/downloads

 

Downloads - ChromeDriver - WebDriver for Chrome

WebDriver for Chrome

sites.google.com

 

주의 해야 할 것은 설치할 크롬 드라이버 버전과 자신의 크롬 버전이 일치해야한다는 것입니다.

버전이 서로 다르면 크롤링이 되지 않습니다.

자신의 크롬 버전 확인: 크롬실행-> 우상단 점3개 아이콘 클릭-> 도움말-> chrome 정보 클릭 하여 확인

설치, 압축 해제 해줍니다. 나중에 이 드라이버를 불러봐야 하기 때문에 저장 위치(경로)를 잘 기억해 둡니다.

 

=================================================

여기까지가 앞으로 몇단계에 걸쳐 진행할 실습을 위한 사전작업 단계입니다.

 

이제 실습 진행해보겠습니다. 

이번시간에 웹의 정보를 크롤링하여 정보를 수집하고, 얻는 정보는 다음과 같습니다.

<웹: 네이버>

1. 코로나 일일 확진자 수

2. 코로나 관련 최근 10개의 이미지

3. 코로나 관련 최근 3개 기사 타이틀, 링크

 

모두 네이버에 검색한 내용을 크롤링하여 정보를 수집하였습니다.

 

 

네이버에 "확진자"를 검색 하면 아래 창이 나타나고, 개발자도구(F12)를 눌러서 확진자 수 데이터를 확인합니다.

 

status_info 영역 내 클래스 안에 em(글꼴 강조) 클래스 안에 2049데이터가 있습니다.

이 2049 데이터를 나중에 select함수 내부에 '2049데이터 위치' 를 넣어서 그 부분만 정보를 추출할 수 있습니다.

div.status_info 안에 em 클래스안에 2049가 있네요.

 

이런식으로 하나씩 정보를 크롤링하여 원하는 정보만 추출할 수 있습니다.

 

크롤링 방법을 다루는 실습은 아니므로 구체적인 설명은 생략하겠습니다.

함수 사용은 거의 동일하고 필요한 부분은 주석으로 대체했습니다.

 

이제 전체 코드를 확인하겠습니다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import telegram
import requests
from telegram.ext import Updater
from telegram.ext import MessageHandler, Filters
from bs4 import BeautifulSoup 
from selenium import webdriver
import urllib.request as req
import os
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
API_key='knI%2FsEhuhoIf37FOmsc8uCq6qdcCXaJU9%2BKHEwgtLzMWGJ7A7LtC3w3Z3JvKzcE4cSrxn6reCcJi2FzIcKvKAQ%3D%3D'
 
options = webdriver.ChromeOptions()
#크롬창을 키지 않고 연결
options.add_argument('headless')
#사이즈 
options.add_argument('window-size=1920x1080')
#GPU설정 X
options.add_argument("disable-gpu")
# 혹은 options.add_argument("--disable-gpu")
driver  = webdriver.Chrome("./chromedriver.exe", options = options) 
#확진자 검색 후 f12로 코로나 확진자 수 정보 컴포넌트 위치 파악 후 크롤링
def covid_num_crawling():
    code = req.urlopen("https://search.naver.com/search.naver?where=nexearch&sm=top_hty&fbm=0&ie=utf8&query=%ED%99%95%EC%A7%84%EC%9E%90")
    #html 방식으로 파싱
    soup = BeautifulSoup(code, "html.parser")
    #정보 get
    info_num = soup.select("div.status_info em")
    result = info_num[0].string #=> 확진자
    return result
 
def covid_news_crawling():
    code = req.urlopen("https://search.naver.com/search.naver?where=news&sm=tab_jum&query=%EC%BD%94%EB%A1%9C%EB%82%98")
    soup = BeautifulSoup(code, "html.parser")
    title_list = soup.select("a.news_tit")
    output_result = ""
    for i in title_list:
        title = i.text
        news_url = i.attrs["href"]
        output_result += title + "\n" + news_url + "\n\n"
        if title_list.index(i) == 2:
            break
    return output_result
 
def covid_image_crawling(image_num=5):
    if not os.path.exists("./코로나이미지"):
        os.mkdir("./코로나이미지")
 
    browser = webdriver.Chrome("./chromedriver")
    browser.implicitly_wait(3)
    wait = WebDriverWait(browser, 10)
 
    browser.get("https://search.naver.com/search.naver?where=image&section=image&query=%EC%BD%94%EB%A1%9C%EB%82%98&res_fr=0&res_to=0&sm=tab_opt&color=&ccl=0&nso=so%3Ar%2Cp%3A1d%2Ca%3Aall&datetype=1&startdate=&enddate=&gif=0&optStr=d&nq=&dq=&rq=&tq=")
    wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "div.photo_group._listGrid div.thumb img")))
    img = browser.find_elements_by_css_selector("div.photo_group._listGrid div.thumb img")
    for i in img:
        img_url = i.get_attribute("src")
        req.urlretrieve(img_url, "./코로나이미지/{}.png".format(img.index(i)))
        if img.index(i) == image_num-1:
            break
    browser.close()
 
 
 
#토큰 넘버
token = "토큰"
id = "id값"
 
bot = telegram.Bot(token)
info_message = '''- 오늘 확진자 수 확인 : "코로나" 입력
- 코로나 관련 뉴스 : "뉴스" 입력
- 코로나 관련 이미지 : "이미지" 입력 '''
bot.sendMessage(chat_id=id, text=info_message)
 
updater = Updater(token=token, use_context=True)
dispatcher = updater.dispatcher
updater.start_polling()
 
### 챗봇 답장
def handler(update, context):
    user_text = update.message.text # 사용자가 보낸 메세지를 user_text 변수에 저장
    # 오늘 확진자 수 답장
    if (user_text == "코로나"):
        covid_num = covid_num_crawling()
        bot.send_message(chat_id=id, text="오늘 확진자 수 : {} 명".format(covid_num))
        bot.sendMessage(chat_id=id, text=info_message)
    # 코로나 관련 뉴스 답장
    elif (user_text == "뉴스"):
        covid_news = covid_news_crawling()
        bot.send_message(chat_id=id, text=covid_news)
        bot.sendMessage(chat_id=id, text=info_message)
    # 코로나 관련 이미지 답장
    elif (user_text == "이미지"):
        bot.send_message(chat_id=id, text="최신 이미지 크롤링 중...")
        covid_image_crawling(image_num=10)
        # 이미지 한장만 보내기
        # bot.send_photo(chat_id=id, photo=open("./코로나이미지/0.png", 'rb'))
        # 이미지 여러장 묶어서 보내기
        photo_list = []
        for i in range(len(os.walk("./코로나이미지").__next__()[2])): # 이미지 파일 개수만큼 for문 돌리기
            photo_list.append(telegram.InputMediaPhoto(open("./코로나이미지/{}.png".format(i), "rb")))
        bot.sendMediaGroup(chat_id=id, media=photo_list)
        bot.sendMessage(chat_id=id, text=info_message)
      
    
        
echo_handler = MessageHandler(Filters.text, handler)
dispatcher.add_handler(echo_handler)
cs

 

결과 화면입니다.

 

 

실시간 도착 버스 정보 조회 API를 신청하고나서 

짧게는 1시간 길게는 2일 정도 사용허가를 해준다 그랬는데 신청하고 20분후에 아래 처럼 승인이 나 있었습니다.

 

되게 빨리 됐다 싶어서 바로 사용해보려고 상세기능의 샘플코드로 테스트해보기 위해 busRouteId를 입력했더니

아래처럼 오류가 났습니다.

처음엔 잘 몰랐어서 오류를 보고나서 전용 API키를 발급받아야되나? 내가 어떤 잘못을 했나? 싶어서 다시 시도해봤는데

계속 오류가 떳습니다..

 

오류를 검색 했더니 이는 공공기관 서버 쪽에서 아직 처리가 안된거라고 합니다.

어느정도 시간이 지나서(야식을 먹고 새벽에..) 다시 시도해보니.

 

아래처럼 오류문구가 바꼈습니다. 이제는 인증실패가 아니라 결과가 없다고 나오네요.

처음에는 새벽에 버스가 운행을 하지않기 때문에 데이터가 없다고 출력됐다고 생각했는데,

이는 입력 데이터가 잘못된 것입니다. 즉, 승인 허가는 났고 이제 잘못된 데이터를 넣어서 오류가 난것이죠.

 

 

올바른 값을 넣으면 아래처럼 잘 나옵니다.

저는 api사용 신청 후 실제 사용 허가 까지 2시간 정도 걸린 것 같습니다.

 

 

 

최근에 크롤링에 대해서 공부했는데 매우 쉽고 금방 써먹을 수 있어서 이를 어떻게 응용해볼까 생각하다가 텔레그램을 활용한 챗봇을 만들어보고자 본 튜토리얼을 진행하게되었습니다.

저는 VScode에서 python으로 진행했습니다.

 

순서는 다음과 같습니다.

 

1. 텔레그램 설치(토큰 값 저장)

2. 메세지 보내고 응답받기

 

 

1. 텔레그램 설치

구글 스토어에서 텔레그램을 설치합니다.

돋보기 클릭 후 'botfather' 이라고 검색한 뒤 클릭합니다.

 

'/newbot' 입력 후 새 봇 이름을 설정해줍니다. (채팅방 이름)

이제 채팅방에 접속하기 위한 봇 이름(계정 이름 같은?) 을 설정합니다 . 끝자리는 무조건 'bot'이 들어가야하며 중복 에러 발생 시 새 이름을 지어야합니다.

메세지 중간 부분에 토큰 아이디가 나오는데 이를 복사 해 두도록 합니다. 이 정보를 이용해 챗봇과 연결할 수 있습니다.

이제 나가서 다시 돋보기로 봇이름을 검색해봅니다. 아래와 같이 나올것이며 접속 후 시작 버튼을 눌러줍니다.

 

2. 메세지 보내고 응답받기

채팅방에 접속하여 아무런 메세지나 입력해도 아무 반응이 없습니다.(정상입니다)

메세지를 보내기 위해 우리는 token값과 id정보를 이용해야 하는데 token값은 알고 있으니 id정보를 얻을차례입니다.

 

이제 vscode에서 터미널에 아래 명령어로 패키지를 깔아줍니다.

 

pip install python-telegram-bot

 

그리고 아래 코드를 입력 후, 실행해봅니다.

1
2
3
4
5
6
7
import telegram
 
token = '토큰 id'
bot = telegram.Bot(token=token)
updates = bot.getUpdates()
for u in updates:
    print(u.message)
cs

에러가 날 경우 채팅방에 몇마디 입력한 뒤 다시 실행합니다. 아래와 같은 정보들이 터미널에 뜰 텐데 id값을 복사하여 역시 복사해둡니다. 제 id는 1954654082네요.

 

이제 텔레그램 봇이 자동으로 나에게 하나의 메세지를 전달해보도록 하겠습니다.

아래 코드를 입력 후 실행합니다. 

1
2
3
4
5
6
7
import telegram
 
token = "토큰 id"
id = "터미널에서 확인한 id값"
 
bot = telegram.Bot(token)
bot.sendMessage(chat_id=id, text="테스트 코드")
cs

 

텔레그램에서 "테스트 코드"라는 메세지가 도착했을겁니다.

 

이제 우리가 메세지를 보내면 응답을 받는 코드를 작성해보겠습니다.

updater, start_polling, handler함수 등이 있는데 handler함수를 조절하여 메세지 핸들러를 생성한 후 이를 디스패처 변수의 add_handler함수를 이용하면 메세지가 푸쉬되는것입니다. 

handler함수를 조정하여 간단하게 테스트해보겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import telegram
from telegram.ext import Updater
from telegram.ext import MessageHandler, Filters
 
token = "토큰 값"
id = "id 값"
 
bot = telegram.Bot(token)
 
 
# updater
updater = Updater(token=token, use_context=True)
dispatcher = updater.dispatcher
#봇 
updater.start_polling()
 
def handler(update, context):
    user_text = update.message.text 
    if user_text == "ㅋㅋ"#ㅋㅋ라고 보내면 왜웃냐고 답장
        bot.send_message(chat_id=id, text="왜 웃냐"# 답장 보내기
    elif user_text == "웃겨서"
        bot.send_message(chat_id=id, text="뭐가 웃긴데?"# 답장 보내기
 
echo_handler = MessageHandler(Filters.text, handler)
dispatcher.add_handler(echo_handler)
cs

 

결과는 아래와 같습니다. 

 

매우간단하죠?

 

오늘 간단한 챗봇 기능까지 구현하였고 다음시간부터 데이터 크롤링 + 오픈API를 사용하여 다양한 기능들을 추가해보겠습니다.

 

이번시간에는 도커가 설치된 윈도우에서 우분투 컨테이너의 웹에 접속해보겠습니다.

우분투 서버관리 / 웹 배포 등을 위한 기본적인 단계라고 생각하면됩니다.

 

우선 window powershell 또는 도커 데스크탑 CLI모드에 들어갑니다.

 

1. 프로세스 상태 확인: docker ps -a (중지 상태인 컨테이너를 포함한 모든 컨테이너를 출력해줌)

* docker ps만 입력하면 실행 중인 컨테이너 목록만 출력됩니다.

 

2. 컨테이너 실행: docker start ubuntu_server(컨테이너 이름)

3. 원격 접속: docker attach ubuntu_server

 

우분투 컨테이너 이름이 ubuntu_server일 때 다음과 같이 하나의 명령문으로 실행할 수도 있습니다.

docker exec -it ubuntu_server bash   or  docker exec -it ubuntu_server /bin/bash

 

그리고 우선적으로 아래 명령어로 우분투가 어떤 ip를 갖고 있는지 확인해봅니다.

ifconfig

 

실행이 안됩니다.

우리가 설치한 우분투는 저번에도 언급했듯이 빈껍데기 그 자체라서 모든 필요 패키지를 설치해줘야합니다..

아래 명령어로 net-tools를 설치해준 뒤 다시 ifconfig명령어를 입력해봅니다.

 

apt-get install net-tools

 

eth0 네트워크 인터페이스에 내부망 주소 172.17.0.2가 할당 되어있는 것을 확인할 수 있습니다.

도커 컨테이너를 실행하면 기본적으로 컨테이너의 네트워크 환경은 NAT으로 설정되어있습니다.

NAT내부망에서 동작하기 때문에 외부에서 컨테이너 내부로 접속이 불가능합니다.

이는 VM방식과 동일합니다. Vmware나 Virtual Box에서 기본적으로 네트워크 환경이 NAT으로 설정되어 있어(물론 변경 가능) 호스트에서 VM 내부 OS로 , 그리고 그 반대의 경우에도 서로 ip접속이 불가능 했습니다.

이를 Bridged모드로 변경하여 호스트와 통신할 수 있습니다. (같은 공유기에 연결되어 있을 경우)

이는 포트포워딩 방식을 이용한 것인데, 우리 실습 과정에도 포트포워딩을 통해 우분투 컨테이너와 호스트가 통신할 수 있습니다.

 

이제 호스트9000번 포트와 컨테이너 80포트를 바인딩하고 우분투에 아파치를 설치하여 호스트에서 접속해보겠습니다.

호스트에서 바인딩 할 포트넘버는 사용가능한 포트, 즉 사용중이지 않은 포트를 사용해야합니다.

이는 CMD창에서 netstat명령어로 확인할 수 있습니다.

 netstart명령어는 자신의 컴퓨터와 연결된 모든 네트워크 연결을 보여줍니다.

말 그대로 현재 연결된 네트워크만 보여주므로 아래 명령어처럼 옵션을 붙여서 사용가능한 포트를 확인합니다.

 

netstat -ano 명령어로 확인할 수 있습니다.

-a: 모든 포트 표시

-n: ip주소:포트 형태로 표시

-o: PID(프로세스 ID) 표시

뭐가 엄청 많이 나오는데, 상태가 LISTENING일 경우 현재 해당 프로세스가 연결대기 중인 상태이고  ESTABLISHED일 경우 연결되어 사용 중인 포트입니다. LISTENING, ESTABLISHED상태의 포트는 사용할 수 없기 때문에 나열된 포트 숫자 중에서 중간에 숫자 범위에 포함되는 아무 포트나 사용하거나 LISTENING 상태인 프로세스를 kill해서 해당 포트를 사용하면됩니다.

그냥 깔끔하게 LISTENING 상태의 네트워크 정보만 알고 싶으면 아래 명령어를 사용하면됩니다.

netstat -ano | grep "LISTEN"

이제 포트 하나(9000번)를 선택하여 우분투 포트와 바인딩 시켜보겠습니다.

* 위 이미지에 나와있지 않은 포트를 사용하는 겁니다.

 

다시 도커로 돌아와서 새 컨테이너를 생성합니다.

이미 생성한 컨테이너가 있으면 다시 생성하여 설정해야 하므로 새 컨테이너를 생성하여 포트포워딩 해주겠습니다.

아파치 웹서버를 설치할건데, 아파치는 기본 포트가 80이므로 80으로 바인딩해주겠습니다.

* 아파치 웹은 기본 포트가 80이기 때문에 포트포워딩할 때 다른 포트넘버를 넣어주면 정상작동이 되지 않 습니다.

컨테이너 실행-> 접속단계입니다. 컨테이너 이름은 ubuntu_apache로 지어주었습니다. 9000번 포트를 컨테이너 80번 포트로 포워딩 해보겠습니다.

docker run -it --name ubuntu_apache -p 9000:80 ubuntu /bin/bash

"-p 9000:80" 이 눈에 띄는데, 호스트의 9000번포트를 컨테이너의 80번포트로 바인딩 시켜주는 것입니다.

 

새로운 컨테이너므로 똑같이 빈 껍데기 이므로 패키지를 업데이트 해주고 아파치2를 설치합니다.

나중에 ip를 확인할 일이 있을테니 net-tools 도 설치해주었습니다.

apt-get update

apt-get install net-tools

 

ifconfig로 ip를 확인해보니  172.17.0.3으로 할당되어있습니다. 저번에 설치한 ubuntu_server 컨테이너의 아이피는 172.17.0.2였는데, 도커 컨테이너 내부 IP가 172.17.0.x 형태로 할당 됨을 알 수 있습니다.

아파치를 설치합니다.

apt-get install apache2

 

아파치 설치 중간에 지역을 선택하라고 나오면 Asia-> Seoul로 설정하면됩니다.

 

이제 아파치의 버전 정보와 현재 상태를 확인합니다.

apachectl -version

service status apache2

그리고 실행을 시켜줍니다. 

service apache2 start (종료는 stop, 재시작은 restart)

 

systemd패키지가 없어서 systemctl status apache2 명령어는 인식이 안되므로, 위 명령어로 실행해주세요.

 

* 최초 실행 시 아래 에러 문구가 뜰 수 있습니다.

ah00558: apache2 could not reliably determine the server's fully qualified domain name

 

오류 내용을 검색해보니 접속할 도메인 이름을 설정하라는 건데, 지금은 외부->도커 웹 연결만 확인하면 되므로 굳이 지정해줄 필요는 없습니다. 다시 service apache2 start 명령어를 입력하면 정상 실행됩니다.

이제 우분투 컨테이너의 웹 브라우저와 호스트의 크롬에서 아파치 실행을 확인해봅니다.

Docker Desktop을 키고 컨테이너 목록에서 오른쪽에 있는 첫번째 아이콘을 입력하면 됩니다.

 

localhost:9000으로 기본 입력되어있고 아파치 디폴트 페이지가 잘 보입니다. 숫자9000은 아까 호스트 포트를 컨테이너80번에 바인딩시켜준 번호입니다.

windows powershell을 하나 더 띄워서 ps -a명령어를 입력하면 포트포워딩 정보를 알 수 있습니다.

 바인딩 할 때 프로토콜 옵션을 조정해주지 않으면 기본 tcp프로토콜이 적용됩니다.

호스트 크롬창에서 똑같이 입력해도 결과는 같습니다. window에서 cmd를 띄워서 호스트 ip를 확인한 다음,

크롬에 ip:9000을 입력해도 똑같이 아파치 화면이 나오는 것을 확인할 수 있습니다.

ex)192.168.122.1:9000

 

아파치 웹서버를 끄고싶다면 터미널에 service apache2 stop 명령어를 입력하시면 됩니다.

 

오늘 우리가 한 내용을 아래 그림으로 요약할 수 있습니다.

 

이제 윈도우(호스트)에서도 우분투 컨테이너 웹서버에 접속할 수 있게 됐습니다!

 

 

 

 

 

 

 

이번시간에는 저번시간에 실습한 우분투 이미지파일을 도커 허브에 업로드 해보겠습니다.

 

도커 허브에 가입하면 클라우드에 저장소를 생성하여 도커 이미지를 저장할 수 있고 필요 시 로컬에 다운로드하여 이용할 수 있습니다. 

도커 이미지 파일 전용 깃허브라고 생각하면 편하고, 사용 방법도 비슷합니다.

다양한 오픈소스 이미지파일이 존재하여 다른 개발자들의 이미지 파일을 이용할 수 있습니다. 

로컬PC 도커에 많은 이미지를 설치해놓으면 나중에 저장공간에 대한 부담도 생겨날 수 있으므로 클라우드에 업로드 시켜놓는 것도 좋은 방법인 것 같습니다.

(퍼블릭 업로드 시 저장 공간의 제한이 없는 것 같습니다.)

 

우선 https://www.docker.com/ 에서 회원가입을 합니다. Docker ID는 닉네임이라고 생각하면됩니다.

그다음, 홈페이지 상단의 Repositories를 클릭한 뒤 Create Repository를 클릭하여 레포지토리 이름을 설정해줍니다.

무료 버전은 공개 저장소는 무제한이지만 사설 저장소는 1개만 생성할 수 있으므로 그냥 public으로 생성해줍니다.

저는 레포지토리 이름을 first_ubuntu로 저장했습니다.

아래와 같이 저장소가 생성된 것을 확인할 수 있습니다.

 

이제 이 저장소에 도커 이미지를 업로드 해 보겠습니다.

windows powershell에서 아래 명령어로 로그인합니다.

docker login

 

저번에 실습한 ubuntu_server 이미지를 업로드 해 보겠습니다.

업로드 하는 과정을 검색해봤는데 기존에 있는 이미지파일을 바로 업로드 할 순 없다고 합니다.

그래서, 고유한 이름으로 새로 생성해서 업로드해야합니다.

 

계속 진행하겠습니다. 원본 이미지 이름은 docker ps -a 명령어를 입력 후 NAMES로 확인할 수 있습니다.

이 때 양식을 잘 맞춰주어야합니다. "도커ID"/"레포지토리 이름"이 들어가야합니다.

양식은 아래처럼 작성해줍니다. 아래 결과로 jow1025/first_ubuntu라는 이름의 이미지가 생성됩니다.

docker commit ubuntu_server jow1025/first_ubuntu:1.0

':' 뒤의 숫자 1.0은 태그 이름입니다. 

* 위의 이미지에서 "editor_vim" 커밋메시지가 반영이 안되는 것 같습니다. 

그냥 docker commit ubuntu_server jow1025/first_ubuntu:1.0 으로 입력해주세요.(본인 설정에 맞게)

 

- 원본 컨테이너 이름: ubuntu_server

- 새로 생성할 이미지: jow1025/first_ubuntu:1.0

- jow1025: 회원가입 때 기입한 도커 ID 

- first_ubuntu: 도커 허브 레포지토리 이름

- 1.0 : 태그이름, 이미지 id를 쉽게 식별하기 위한 목적

 

생성 후 docker images 명령어를 통해 새로 생성된 이미지를 확인합니다.

이름은 jow1025/first_ubuntu로, TAG는 1.0으로 설정되어 있습니다. 

이제 도커 허브에 업로드 하여 확인합니다.

docker push jow1025/first_ubuntu:1.0

도커 허브에서 확인하면 잘 업로드 된 걸 확인할 수 있습니다.

 

이제 도커 허브에 저장된 자기의 도커 이미지를 로컬 PC로 다운받아 보겠습니다. 간단하므로 방법만 설명하겠습니다.

1. 로그인: docker login

2. 이미지 다운: docker pull jow1025/first_ubuntu:1.0

3. 이미지 확인: docker images 

 

 

* 부가 설명

===================================================

우분투에 설치된 도커 이미지를 삭제하는 방법

1. docker images 명령어로 Image ID 확인

2. docker rmi "image id"로 삭제

ex) docker rmi 59c15f3a271e(태그3.0 이미지 삭제)

 

3.결과 확인

 

 

* 컨테이너 삭제는 docker ps 또는 docker ps -a 명령어로 컨테이너 id를 확인한 뒤

docker rm "컨테이너ID"로 삭제할 수 있습니다. 

이미지 삭제/ 컨테이너 삭제 모두 도커 데스크탑 GUI에서 손쉽게 삭제할 수 있습니다.

(계속 windows powershell을 쓰고 있으니 명령어로 제어하고 있는 것임)

=============================================================

 

이상으로 우분투 이미지의 도커허브 업로드/다운로드에 대한 설명을 마치겠습니다.

 

이번시간에는 도커에 우분투를 설치해보겠습니다.

우분투를 설치해서 기존에 제가 사용했던 vmware 리눅스 서버/ AWS ec2처럼 사용할 수 있습니다.

 

windows powershell을 실행합니다.

 

docker명령어로 저번에 설치한 도커의 버전을 한번 확인해봅니다.

docker version을 입력하면 더 자세한 내용을 확인할 수 있습니다.

 

이제 도커 우분투를 설치해보겠습니다. 우분투 OS를 설치하는 걸까요? 

 

아닙니다. 도커 이미지는 도커 컨테이너를 구성하는 파일 시스템과 실행 애플리케이션을 하나로 합친 것으로, 컨테이너를 생성하는 일종의 템플릿 같은 역할을 합니다.

도커 컨테이너는 도커 이미지를 기반으로 생성되며 실제 실행되는 상태를 의미합니다.(격리된 프로세스의 실행)

 

쉽게말해 이미지는 실행파일을, 컨테이너는 프로세스를 의미합니다.

 

그렇기 때문에 제일 먼저 우분투OS를 설치하는게 아니라 우분투 이미지를 설치하는 것입니다.

windows powershell에서 아래 명령어를 입력해줍니다. 해당 명령어를 통해 제일 최신의 우분투 버전을 설치하게됩니다.

docker pull ubuntu

docker images 명령어로 설치된 이미지를 확인합니다.

72MB의 우분투 이미지가 설치되었음을 확인할 수 있습니다.

도커 데스크탑 GUI로도 확인할 수 있습니다. 오늘 설치했는데 15일전에 생성되었다고 나오네요...??

이제 실제로 실행하기 위해 이미지를 컨테이너로 생성해 줄 차례입니다. 아래 명령어를 입력합니다.

2가지 방법이 있는데 편하신 방법대로 하면됩니다. 2번 방법이 훨씬 편하긴합니다.

 

1. 생성 후 실행하기

 1) 생성: docker create -i -t --name ubuntu_server ubuntu

 2) 이미지 상태 확인: docker ps -a 

 STATUS가 Created로 되어있을 겁니다.

 3) 실행: docker start ubuntu_server

 4) 우분투 접속: docker attach ubuntu_server(우분투 커맨드 창으로 넘어감)

2. 생성과 동시에 실행하기(이게 간단해보임)

 1) docker run -i -t --name ubuntu_server ubuntu /bin/bash

 명령어 입력 후 우분투 터미널로 이동합니다. 

 

부가설명)

===============================================

 -i: stdin(상호 입출력)

 -t: tty(터미널)을 활성화

 즉, 실행될 Bash셸에 입출력을 하겠다는 의미(명령어를 입력하면 우분투 커맨드 창으로 넘어감)

 - ubuntu /bin/bash: 우분투 이미지 안의 bin/bash를 실행

 - ubuntu_server: 설정한 컨테이너 이름(자유롭게 설정)

 - 2번 방법은 최초에 생성과 실행을 동시에 해줄 뿐이고 다음부터 실행할 때는 1번 방법의 3번 명령어부터 실행해야합니다.

 - 컨테이너 종료: exit (우분투 쉘에 있을 때 )

 - 컨테이너 종료: docker stop ubuntu_server (widows powershell에 있을 때)

===============================================

 

도커 데스크탑 GUI와 windows powershell에서 컨테이너의 실행 상태를 확인할 수 있습니다.

아래 이미지에 나와있는 첫번 째 컨테이너는 저번에 실행한 튜토리얼 컨테이너입니다.

윈도우 쉘에서는 docker ps -a명령어로 컨테이너 상태를 확인할 수 있습니다.

ubuntu_server라는 이름의 컨테이너가 방금 실행되었음을 확인할 수 있습니다.

 

이제 우분투 터미널에서 우리가 설치한 우분투 버전을 확인해 보겠습니다.

현재 설치된 우분투 이미지가 20.04.2 LTS 버전임을 확인할 수 있습니다!

 

현재 우분투 쉘은 말그대로 정말 아무것도 없는 상태라서 필요한 패키지를 다운받아서 사용해야합니다.

기본적인 에디터 조차 설치가 안되어있네요..

패키지 설치 전에는 항상 두 명령어를 먼저 실행해줍니다. (sudo 명령어도 안먹히므로 빼고 입력해줍니다.)

apt-get update

apt-get upgrade

 

기본적인 에디터를 설치하는 것으로 이번시간을 마치겠습니다.

저는 평소에 nano에디터를 사용했는데 vi/vim을 공부해볼 겸 vim 에디터를 설치해주었습니다.

apt-get install vim

제가 블로깅 하기 전에 이미 깔아놔서 아래와 같은 결과가 나옵니다.

터미널에 vim을 입력하면 vim창이 나타납니다.

 

이상입니다.

 

이번에는 직접 도커를 설치해보도록 하겠습니다.

도커 홈페이지에 접속합니다.

https://www.docker.com/

 

Empowering App Development for Developers | Docker

Learn how Docker helps developers bring their ideas to life by conquering the complexity of app development.

www.docker.com

상단 배너에서 Developers -> Getting started를 클릭합니다.

그리고 Docker Desktop 윈도우 버전을 다운로드합니다.

 

중간의 체크박스들은 모두 체크해주시면 됩니다. 설치에 어느정도 시간이 걸리고, 설치 완료 후 재부팅해줍니다.

 

재부팅 하고나면 아마도 아래 이미지 처럼 오류창이 뜰 것 입니다. (안떴다면 도커 실행)

저의 윈도우 환경은 window10 Home인데 대부분 아래 오류가 뜨는 것 같습니다.

 

도커는 리눅스 커널 기능을 이용하여 프로세스를 격리시켜 독립적으로 실행될 수 있도록 도와주기 때문에

WSL(Windows Subsystem for Linux, 리눅스용 윈도우 하위 시스템)라는 프로그램이 필요합니다. WSL2는 WSL보다 대폭 개선된 버전이라고합니다.

 

Window 10 Home의 경우 위 이미지와 같은 오류가 계속 뜰텐데, 이를 설치해주어야합니다.

window 검색창에 windows powershell을 관리자 권한으로 실행합니다.

그리고 아래 순서대로 명령어를 입력해줍니다.

1. 리눅스 서브시스템 활성화

dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart

2. 가상 머신 플랫폼 기능 활성화

dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

3. x64용 WSL2 리눅스 커널 업데이트 패키지 설치

wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi 

 

4. 도커 재시작

 

이제 도커가 작동되는지 튜토리얼로 확인해봅니다. start버튼을 누르면 아래와 같은 화면이 뜨게됩니다.

위에 나온 명령어를 windows powershell에 입력해줍니다.

도커의 containers/apps에 아래 처럼 컨테이너가 정상적으로 러닝되고있음을 알 수 있습니다.(이름은 제각각)

그리고 이제 윈도우 크롬에서 127.0.0.1을 입력해봅니다. 아래와 같이 도커 튜토리얼 사이트가 나와야 정상입니다.

 

도커에서 방금 실행한 튜토리얼 컨테이너가 어떤 환경으로 구성된건지 보겠습니다.

도커 컨테이너 창에서 CLI모드로 입장합니다.

cat etc/issue명령을 통해 리눅스 3.13버전의 환경임을 알 수 있습니다.

 

여기까지가 기본 설치 단계이고 다음시간에는 도커에 우분투를 설치해보겠습니다.

+ Recent posts