Elastic Search 정리

  • 아파치 루씬 기반의 Java 오픈소스 분산 검색엔진임

  • ES를 통해 루씬 라이브러리를 단독으로 사용할 수 있게됨

    • 많은 양의 데이터를 빠르게, 거의 실시간(NRT, Near Real Time)으로 저장, 검색, 분석할 수 있음
  • ELK 스택이란 다음과 같음

    • Logstash
      • 다양한 소스(DB, csv, …)의 로그 또는 트랸쟉션 데이터를 수집, 집계, 파싱하여 ES로 전달
    • Elasticsearch
      • Logstash 로 전달 받은 데이터를 검색 및 집계해서 필요한 관심 정보를 획득
      • http://localhost:9200/
    • Kibana
      • ES의 빠른 검색을 통해 데이터를 시각화 및 모니터링함
      • 키바나는 JVM에서 실행되는 엘라스틱서치와 로그스태시와 달리 node.js로 실행하는 웹애플리케이션임
      • http://localhost:5601/

{: height=”50%” width=”50%”}

  • RDB와 Es 비교

    • Database -> Index
    • Table -> Type
    • column -> Field
    • row -> Document
      {: height=”50%” width=”50%”}
      {: height=”50%” width=”50%”}
  • ES 아키텍쳐 / 용어 정리
    {: height=”50%” width=”50%”}

    • 클러스터
      • 노드들의 집합
      • 서로 다른 클러스터는 데이터의 접근, 교환이 불가
    • 노드
      • ES를 구성하는 하나이 단위 프로세스임
      • 역할에 따라 Master-eligible, Data, Ingest, Tribe 등으로 구분 가능
        • Master-eligible: 클러스터 제어하는 마스터 노드 (인덱스 생상, 삭제 / 클러스터 노드 추적, 관리 / 데이터 입력시 어느 샤드에 할당할지 결정)
        • Data node: CRUD 작업과 관련있는 노드 (CPU, 메모리를 많이 써서 모니터링 필요함, Master node와 분리되는 것이 좋음)
        • Ingest node: 데이터 변환, 사전 처리 파이프라인
        • Coordination only node: 로드밸런서와 비슷한 역할
    • 인덱스 (index), 샤드 (Shard), 복제 (Replica)
      • 인덱스: RDB의 DB와 대응됨
      • 샤드: 데이터 분산해서 저장하는 방법임. scale out을 위해 index를 여러 shard로 쪼갬. 기본적으로는 1개 존재하고 나중에 개수 조정가능
      • 복제: 또 다른 형태의 shard라 할 수 있음. 노드를 손실했을 경우 데이터 신뢰성을 위해 샤드들 복제하는 것. 그러므로 replica는 서로 다른 노드에 존재하는 것이 좋음
        {: height=”50%” width=”50%”}
  • ES 특징

    • Scale out: 샤드를 통해 규모가 수평적으로 늘어날 수 있음
    • 고가용성: replica를 통해 데이터 안정성 보장
    • Schema Free: json 문서를 통해 데이터 검색을 수행하므로 스키마 개념이 없음
    • Restful: 데이터 CRUD 작업은 HTTP Restful API를 통해 수행함
      {: height=”50%” width=”50%”}
  • 예시 (document (row) 생성)

    1
    # curl -XPOST 'localhost:9200/victolee/blog/1?pretty' -d '{"postName" : "elasticsearch", "category" : "IT"}' -H 'Content-Type: application/json'
    • -d 옵션

      • 추가할 데이터를 json 포맷으로 전달합니다.
    • -H 옵션

      • 헤더를 명시합니다. 예제에서는 json으로 전달하기 위해서 application/json으로 작성했습니다.
    • ?pretty

      • 결과를 예쁘게 보여주도록 요청
    • 결과:

      • 이렇게 curl 요청을 하면, victolee 인덱스에, blog 타입으로 id 값이 1인 document가 저장됨
        {: height=”50%” width=”50%”}
  • 역색인 (Inverted Index)

  • 키바나에서 데이터 삽입 예제

    1
    2
    3
    4
    5
    6
    7
    PUT /my_playlist/song/6
    {
    "title" : "1000 years",
    "artist" : "Christina Perri",
    "album" : "Breaking Dawn",
    "year" : 2011
    }
    • 명령어 설명

      • my_playlist : 여러분의 데이터가 들어갈 인덱스의 이름입니다.
      • song : 만들어질 document의 이름입니다.
      • 6 : 엘리먼트 인스턴스의 아이디입니다. 이 경우에는 song id입니다.
    • 만일 my_playlist가 존재하지 않았다면, 새로운 인덱스인 my_playlist가 만들어짐. document인 song과 id인 6도 똑같이 만들어짐.

    • 값을 업데이트 하기 위해서는 PUT 명령어를 동일한 document에 사용하면 됨. 새로운 필드도 추가 가능함
      {: height=”50%” width=”50%”}

    • GET 명령어 쓰면 값 불러옴

      1
      GET /my_playlist/song/6

      {: height=”50%” width=”50%”}

    • 데이터 선택하는 조건문 예시

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      # state가 UT인 데이터 가져오기
      GET /bank/_search?q=state:UT

      # state가 UT이거나 CA인 데이터 가져오기
      GET /bank/_search?q=state:UT OR CA

      # state가 TN이면서 여성(female)인 데이터 가져오기
      GET /bank/_search?q=state:TN AND gender:F

      # 20살보다 많은 나이를 가진 사람들 가져오기
      GET /bank/_search?q=age:>20

      # 20살과 25살 사이의 데이터 가져오기
      GET /bank/_search?q=age:(>=20 AND <=25)
    • 좀 더 복잡한 질의

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      # address 필드에서 Street이라는 단어가 포함되어야 함
      # gender 필드에서 f가 정확히 일치하여야 함
      # age 필드에서 숫자는 25보다 크거나 같아야 함
      GET /_search
      {
      "query": { //1
      "bool": { //2
      "must": [
      { "match":{"address":"Street"}} //3
      ],
      "filter": [ //4
      { "term":{"gender":"f"}}, //5
      { "range": { "age": { "gte": 25 }}} //6
      ]
      }
      }
      }

Kibana

  • 데이터는 ES에 올라가 있어야함
  • ES 인덱스(DB)에 저자된 데이터를 키바나가 인식할 수 있도록 인덱스를 설정해야함

데이터 복구

자세히 보기

ML Basic - 머신러닝과 확률

Prior & Posterior

  • 사전 확률(prior probability):

    • 관측자가 관측을 하기 전에 시스템 또는 모델에 대해 가지고 있는 선험적 확률. 예를 들어, 남여의 구성비를 나타내는 p(남자), p(여자) 등이 사전확률에 해당한다.
    • 특정 사상이 일어나기 전의 확률을 뜻한다.
    • 선험적 확률은 베이즈 추론에서 관측자가 관측을 하기 전에 가지고 있는 확률 분포를 의미한다.
    • ex) 동전을 던져서 앞면이 나올 확률은 1/2, 특이한 동전은 1/3이다.
    • 사전 확률은 일반적으로 실험하는 대상에 대해 잘 알고 있는 전문가가 선택하거나(informative prior), 혹은 전문적인 정보가 없는 무정보적 분포(uninformative prior)로 주어진다.
  • 사후 확률(Posterior):

    • 사건이 발생한 후(관측이 진행된 후) 그 사건이 특정 모델에서 발생했을 확률
    • 사건 발생 후에 어떤 원인으로부터 일어난 것이라고 생각되어지는 확률
    • 조건부 확률을 통해 사후 확률을 표현할 수 있음
    • 사전 확률과 가능도(likelihood)가 주어졌을 때, 관측자는 관측값을 얻은 다음 베이즈 정리에 의해 사후 확률을 얻을 수 있음
    • ex) 물건이 불량품이 생산되었을때 A공장에서 생산되었을 확률
    • $posterior = {likelihood \times prior \over evidence}$

MLE & MAP 예시

  • MLE(Maximum Likelihood Estimation) 방법

    • MLE 방법은 남자에게서 그러한 머리카락이 나올 확률 p(z|남)과 여자에게서 그러한 머리카락이 나올 확률 p(z|여)을 비교해서 가장 확률이 큰, 즉 likelihood가 가장 큰 클래스(성별)를 선택하는 방법
  • MAP(Maximum A Posteriori) 방법

    • MAP 방법은 z라는 머리카락이 발견되었는데 그것이 남자것일 확률 p(남|z), 그것이 여자것일 확률 p(여|z)를 비교해서 둘 중 큰 값을 갖는 클래스(성별)를 선택하는 방법
    • 즉, 사후확률(posterior prabability)를 최대화시키는 방법으로서 MAP에서 사후확률을 계산할 때 베이즈 정리가 이용됨
  • 즉 MLE는 남자인지 여자인지를 미리 정해놓고 시작해서 비교하는거고 MAP는 남자인지 여자인지를 모르는 상태에서 그것이 정해지는 확률까지도 고려해서 비교하는 것임

  • MAP가 그래서 특정 경우가 정해지는 것에 대한 사전확률을 고려한다고 하는 것임

Maximum Likelihood Estimation (MLE)

Maximum a Posteriori Estimation (MAP)

자세히 보기

Research to Production

Research

  • 개발 기간이 필요함
  • 어떤 데이터를 쓸지 어떤 데이터를 모을 수 있을지 어디까지 라벨링 할 수 있을지, 어떤 데이터로 원하는 데이터를 비슷하게 대체할 수 있을지 등을 생각해야함
  • 대략적인 시간을 산정해서 보고해야함
  • 논문을 많이 읽으면 읽을수록 좋긴함
  • 갖다 쓸수있는건 빠르게 갖다 써야함
    • 케글이나 이런데서 빠르게 참조할 필요가 있음
  • 프로토 타이핑은 매우 빠르게~!
  • 개인적으로는 처음부터 좋은 모델보단 baseline부터 서서히 올려가는게 결과를 확인하고 model capacity를 조정하면서 추후 모델 선택할 때 좋음
  • Speed한 프로토타이핑이 생명 (빠르게 짜는게 중요함, gpu로 학습한다고 노는것도 별로 안좋음)
  • Hyper Params 에 대한 실험 관리 + feature에 대한 실험 관리 도구가 좀 필요함
  • git 관리를 잘해야함
  • 안해본 것에 대한 두려움이 없어야함
  • DL Framework
    • Prototyping: PyTorch
    • Service: TensorFlow or PyTorch
      • eager mode로 logit + loss 까지 tensor format & shape 확인
      • graph mode로 학습시켜서 pb 추출
  • AutoML: 어떤 오픈소스 쓸지 TBD
  • 앙상블까지 고려해야함
    • Model 관리하는 configuration 부분이 매우 귀찮아질 수 있음 (여러개의 모델을 사용하기 때문에)
    • Data driven Software 될 수 있게 코드단이 아니라 configuration으로 모델의 구조를 변경 할 수 있어야함 (caffe나 claf 처럼)
  • 처음 모델 짤때는 파이프라인+간단한 구조부터해서 구조를 업데이트하는 쪽으로 방향을 잡고 짜야함
  • 모델평가를 쉽게 돌리고 비교할 수 있는 파이프라인..!이 필요함
  • feature store를 어떻게 구성할지, 실시간 학습 어떻게 구성할지 고민

Production

  • 환경셋팅 문서화 (한번에 뜨고 설치할 수 있게 도커가 그립다)
  • 클래스, 플로우 다이어그램: PlantUML (https://meetup.toast.com/posts/117)
  • 다이어그램 & 마인드맵 그리고 개발하면 좋음
  • L4 (Load Balancer)
    • L4에서는 1초간 계속 health check를 해서 서버 하나가 꺼지면 떼버리고 다시 살아있으면 붙임
    • 반응못하면 아마 500에러 낼듯
  • 네트워크 프로토콜
  • healthcheck
    • 프로세스 관리
    • JandiAlert
  • 부하테스트
    • 실서버와 동일한 환경인 Sandbox가 필요함
    • nGrinder
  • 프로파일링
    • Network Distillation
  • TC 작성 (testcase)
  • DB 연결 부분은 local에서도 테스트 할 수 있게끔 default value를 하나 만들어줘서 debug할 수 있게 해야함
  • pylint등으로 개발스타일 통일
  • 로그 관리
  • 안해본 것에 대한 두려움이 없어야함
  • Jandi Alert Code
  • 상용에서는 로그를 남기기 때문에, 모듈별로 테스트할때 로그가 남을 수 있는데 그러면 안됨! 왜냐하면, 로그를 모듈별로 일치시켜줘야하기 때문에~!(ex, 채팅 클라이언트/채팅API/챗봇엔진) 그러므로 로그를 안남기기 위한 API 테스트를 고려해서 인터페이스를 설계해야함 (로그를 안남기거나, 테스트를 위한 로그를 따로 남겨야함)
  • 디펜던시 없는 테스트(DB, API 서버등..과 분리)를 위해 테스트 케이스와 모듈을 만들어놔야함. 그래야 배포때 편함.
  • 서버 실행시 자원 얼마나 소모하는지 모니터링, 체크
  • 패치 프로세스 기록 필요함, 연동 테스트용 코드도.
  • Script화 해놔서 다른 사람이 언제든지 사용할 수 있게 해야함.
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
import json
import requests
import linecache
import sys
import os

def jandi_alert(body, server, webhook_url, api="name of API"):
"""
ref: https://drive.google.com/file/d/0B2qOhquiLKk0TVBqc2JkQmRCMGM/view

ERROR_COLOR = "#FF0000";
INFO_COLOR = "#0000FF";
WARNING_COLOR = "#FFFF00";
DEFAULT_COLOR = "#FAC11B;
"""

# ref: https://stackoverflow.com/questions/14519177/python-exception-handling-line-number
exc_type, exc_obj, tb = sys.exc_info()
f = tb.tb_frame
lineno = tb.tb_lineno
file_name = f.f_code.co_filename
linecache.checkcache(file_name)
line = linecache.getline(file_name, lineno, f.f_globals)
# print 'EXCEPTION IN ({}, LINE {} "{}"): {}'.format(filename, lineno, line.strip(), exc_obj)
file_name = os.path.basename(file_name)

payload = {
"body": body,
"connectColor": "#FF0000",
"connectInfo": [{
"title": "___ 서버 이상",
"description": "server: {}\napi: {}\nfile_name: {}\nLINE {} '{}': {}".format(server, api, file_name, lineno, line.strip(), exc_obj)
}]
}

requests.post(
webhook_url, data=json.dumps(payload),
headers={'Accept': 'application/vnd.tosslab.jandi-v2+json',
'Content-Type': 'application/json'}
)


자세히 보기

gPRC + Healthcheck 뽀개기

gRPC 개념 설명

gRPC 사용할 때 주의할점

  • retry 이슈
    • gRPC는 HTTP2 기반인데, 양방향 통신이라 커넥션을 계속 붙잡고 있는데, 이게 가끔 30분에 한번씩 끊길때가 있다 (뭐가 헤더 크기를 넘어가면서..어쩌구저쩌구 들었던거 같은데 다시 찾아봐야함)
    • 그럴땐 클라이언트 쪽에서 보낸 요청이 fail되고 서버가 못듣게 되는데 단순히 클라가 한번 더 retry해주면 된다.
    • 보통 http2를 쓰는 프로토콜은 retry 로직이 필수라한다
  • 헬스체크 이슈 (ulimit, channel close, Too many open files)
    • grpc는 status 를 제공하고 health check 프로토콜도 제공한다. 어찌다가 try except으로 에러날때 status 코드를 꺼내는 방식으로 꼼수로 구성한적이 있었다..(이럼 안되지.. 이것 때문에 연차썼다가 출근해서 반차처리한 적이..흑흑)
    • 이때 grpc connect을 따로 close해주지 않으면 소켓연결이 쌓이게 되고 리눅스 운영체제에서 file open개수에 대한 ulimit을 초과하면 Too many open files 에러가 뜬다
    • 보통 이런경우 ulimit을 올려주면 되지만, 근본적인 에러원인인 소켓 증가 이유를 찾아야했고 찾다보니 health check때 retry 이슈로 except뜬게 쌓이고 있었다는 결론을 내렸다
    • 결과적으로 connect close를 잘해주자 안그러면 too many file opens 에러뜨니까

gRPC.proto 살펴보기

  • filename: projectname.proto
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
// Copyright 2015 The gRPC Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
syntax = "proto3";

option java_multiple_files = true;
option java_package = "com.eagle705.demogrpc.proto.projectname";
option objc_class_prefix = "projectname_prefix";

package projectname;

// Interface exported by the server.
service Chatbot {
// A simple RPC.
//
// Obtains the feature at a given position.
//
// A feature with an empty name is returned if there's no feature at the given
// position.

rpc 호출할함수명(input자료구조명) returns (stream output자료구조명) {}

// A server-to-client streaming RPC.
//
// Obtains the Features available within the given Rectangle. Results are
// streamed rather than returned at once (e.g. in a response message with a
// repeated field), as the rectangle may cover a large area and contain a
// huge number of features.
// rpc ListFeatures(Rectangle) returns (stream Feature) {}

// A client-to-server streaming RPC.
//
// Accepts a stream of Points on a route being traversed, returning a
// RouteSummary when traversal is completed.
// rpc RecordRoute(stream Point) returns (RouteSummary) {}

// A Bidirectional streaming RPC.
//
// Accepts a stream of RouteNotes sent while a route is being traversed,
// while receiving other RouteNotes (e.g. from other users).
// rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
}

// 프로퍼티에 입력되는 값을 순서를 의미하는 듯?!(TBD: 확인필요)
message input자료구조명 {
string 프로퍼티1 = 1;
int32 프로퍼티2 = 2;
repeated int32 프로퍼티3 = 3; // repeadted는 리스트를 뜻하는 듯
string 프로퍼티4 = 4;
}

message output자료구조명 {
int32 프로퍼티1 = 1;
double 프로퍼티2 = 2;
}
자세히 보기

XGBoost 정리

본 문서는 XGBoost에 대한 기본적인 설명과 설치 가이드에 대해서 다룬 문서입니다.

A. 소개

  • 오픈소스 명: XGBoost
  • Github URL: https://github.com/dmlc/xgboost
  • Ref: Tianqi Chen and Carlos Guestrin. XGBoost: A Scalable Tree Boosting System. In 22nd SIGKDD Conference on Knowledge Discovery and Data Mining, 2016

B. 설치

XGBoost는 CPU전용 설치와 GPU전용 설치 두개로 나뉜다.
CPU 전용으로 설치한다면,

install xgboost``` 를 해버리면 끝이나
1
2
3
4
5
6
7
실제로 사용하려고 하면, Decision Tree보다 느린 속도를 체감하게 되므로 자연스럽게 GPU를 쓰게 된다.   
GPU 전용으로 설치하려면, 소스로부터 직접 컴파일 해야한다.
XGBoost에서는 install guide를 제공해주고 있는데, 현재까지 나온 install guide에는 약간의 문제가 있는데 바로 multi-gpu 관련 문제다. multi-gpu를 사용하기 위해선 GPU간의 communication을 담당해주는 **NCLL**(pronounced "Nickel") 이라는걸 셋팅해줘야하는데 기본 가이드에선 본 셋팅이 빠져있기 때문이다.
설치 가이드: http://xgboost.readthedocs.io/en/latest/build.html#building-with-gpu-support
교정된 내용 출처: https://github.com/dmlc/xgboost/issues/2915

Ubuntu기준 전체적인 설치 프로세스는 다음과 같다.

git clone –recursive https://github.com/dmlc/xgboost
git submodule init
git submodule update

자세히 보기

온톨로지와 RDF에 대한 개념설명 및 생성방법

본 Knowlede base를 구축하기 위해 온톨로지 및 RDF에 관한 설명, 문법 그리고 생성방법에 대해 다룬 문서입니다.

A. 소개

B. Ontology 구축 툴

C. RDF 구축 툴

자세히 보기

DBpedia 셋팅

본 문서는 챗봇과 Knowlede base를 연동하기 위해 DBpedia를 설치하고 사용하는 내용을 다룬 문서입니다.

A. 소개

B. 설치

virtuoso 설치

1
2
3
4
5
brew install virtuoso
vi ~/.zshrc
// 수정 아래처럼!
export VIRTUOSO_HOME="/usr/local/Cellar/virtuoso/7.2.4.2"
export PATH=$PATH:$VIRTUOSO_HOME/bin

virtuoso 실행

자세히 보기

Vue.js 입문

Vue에 대한 몇가지 속성을 빠르게 파악하기 위해 기록을 남겨둔다. 공식적인 문서를 위주로 참고해서 작성할 예정!

예제1

1
2
3
<div id="app">
{{ message }}
</div>
1
2
3
4
5
6
var app = new Vue({
el: '#app', //DOM의 id를 여기서 입력해주고
data: { // DOM안의 템플릿에 key value 형태로 데이터를 뿌려줌
message: '안녕하세요 Vue!'
}
})

문자열을 단순히 뿌려줌.
자 이제 뿌려주는걸 넘어서 바인딩! 해주는걸 보자.

예제2

1
2
3
4
5
<div id="app-2">
<span v-bind:title="message">
내 위에 잠시 마우스를 올리면 동적으로 바인딩 된 title을 볼 수 있습니다!
</span>
</div>
자세히 보기

Docker 입문

Docker를 처음 입문한건 텐서플로우를 윈도우에 설치하면서부터였다. 뭔가 바로 로컬에서 소스를 수정할 수 있는게 아니라서 뭔가 여간 불편해서 그 이후로 잘 안썼었는데.. 이 도커가 사람들은 정말 편리한지 이제 시장에서 배포환경이 거의다 도커가 되어버렸다(배포는 사실 진짜 편하긴하지..). 최근 회사에서도 도커를 쓸일이 생겨버려서.. 이젠 좀 체계적으로 정리를 해야겠다 싶다.

  • 컨테이너 하나가 하나의 프로세스라고 보면 된다
  • dockerhub는 github같은 오픈된 도커 이미지 저장소다
  • docker id는 앞부분의 일부만 입력해도 실행이 된다

Docker 상태체크

ps -a``` : 실행중인 도커 컨테이너 리스트를 확인
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
```docker images``` : 도커 이미지 목록   
```docker login``` : docker hub계정으로 로그인 가능
```docker restart <도커id>``` : 도커 컨테이너 재실행
```docker attach <도커id>``` : (실행중인)도커 컨테이너에 접속 (웹서버 같이 백그라운드에서 실행되는 컨테이너에 attach로 접속하면 커맨드를 입력할 수 없고 로그인만 볼 수 있음)
```docker inspect <도커id>``` : 도커 컨테이너의 공유폴더나 기타 옵션들을 다 볼수있음!

### Docker 컨테이너 & 이미지 삭제
```docker rm <도커id>``` : 도커 컨테이너를 삭제함
```docker rmi <도커id>``` : 도커 이미지를 삭제함
이미지까지 삭제해줘야 나중에 docker image를 업로드할때 같은 이름일경우 오류가 안남


### Docker 컨테이너 안에 접속
```docker exec <도커id>``` : 컨테이너에 새로운 프로세스를 실행시킬 때 사용함(예를들면 쉘이나.. / 컨테이너가 재시작될때 같이 재시작되진 않는다고 함_체크필요!!)
```docker exec -it <도커id> /bin/bash```: 컨테이너에 접속해서 bash 쉘 실행! (-it 라고 덧붙여 주어야 한다. 이는 STDIN 표준 입출력을 열고 가상 tty (pseudo-TTY) 를 통해 접속하겠다는 의미)
### Docker 컨테이너 안에 파일 복사
```docker cp /path/foo.txt <도커id>:/path/foo.txt```: 호스트에서 컨테이너로 파일 전송하는 방법
```docker cp <도커id>:/path/foo.txt /path/foo.txt```:컨테이너에서 호스트로 파일 전송하는 방법


### Docker 실행
```docker run -d -p 8888:8888 -p 6006:6006 dockerhub계정/이미지이름```: 도커 이미지 다운받고 포트포워딩 후 실행(아마 -d가 다운.. -p가 포트포워딩인듯?)
```docker run -p 443:1443 -p 8080:8000 -itd -v <호스트의 로컬디렉토리>:<컨테이너의 디렉토리> --name <생성할컨테이너이름> <이미지이름>```: -v 옵션으로 공유폴더 마운트를 해줄 수 있음! -d는 백그라운드 옵션
```docker-compose up -d```


### Docker 이미지 업로드
```docker commit -m "<메세지>" <도커id> dockerhub계정/이미지이름:태그```: docker 이미지 커밋(컨테이너에서 이미지 생성, 포트포워딩 새로 짜줄때 많이 씀)
```docker commit <도커id> <이미지이름>```: docker 이미지 커밋(컨테이너에서 이미지 생성, 포트포워딩 새로 짜줄때 많이 씀)
```docker push dockerhub계정/이미지이름:태그```: dockerhub에 이미지 업로드

### Docker 이미지 파일화 및 다시 로딩

#### 컨테이너 To 이미지:태그

sudo docker commit oj-postgres oj-postgres:181107
sudo docker commit oj-backend oj-backend:181107
sudo docker commit oj-redis oj-redis:181107
sudo docker commit judge-server judge-server:181107

1
2

#### 이미지:태그 To 파일(tar)

sudo docker save oj-redis:181107 > oj-redis
sudo docker save oj-backend:181107 > oj-backend
sudo docker save oj-postgres:181107 > oj-postgres
sudo docker save judge-server:181107 > judge-server

자세히 보기