기본 콘텐츠로 건너뛰기

docker+alias를 사용해서 golang 편하게 쓰기

이 글은 docker 설치를 했다는 가정에서 진행한다.

먼저 go docker 버전을 가져오자
docker pull 해도 되지만 필요한 걸 추가할 수도 있을 것 같아
Dockerfile 을 만들었다.
FROM golang:1.7-alpine
go 1.7을 비교적 가벼운 alpine linux버전에 올리자.
docker build .
해서 image를 만들자
docker images를 해서 확인할 수 있다.
alpine 이 아니라 그냥 1.7도 docker pull golang:1.7 해서 가져와봤는데 

$ docker images
REPOSITORY                  TAG                 IMAGE ID            CREATED            SIZE
golang                      1.7-alpine          52493611af1e        5 days ago          241.1 MB
golang                      1.7                 fe25c00086fb        5 days ago          669.6 MB

용량 차이가 제법 난다.
1.7은 안쓸거니까 docker rmi golang:1.7 해서 바이바이.

docker run -it --rm --name migolang golang:1.7-alpine go

작동을 확인해보자. 잘되면 OK. golang:1.7-alpine이 불편하면 docker build -t migolang . 과 같이 태그를 지정할 수도 있다. docker run -it --rm --name migolang migolang go 처럼 쓸 수 있는 것.

옵션에 대해 구구절절 설명을 좀 하면
docker run -it --rm --name migolang golang:1.7-alpine go
-it 옵션은 -i -t 를 붙여서 쓴건데 -i 입력을 유지하는 옵션이고 -t는 TTY 즉 docker 에서 일어난 결과를 화면 포워딩 하는 것으로 사실 이 경우엔 쓸 필요없지만 습관처럼 붙여쓰고 있다.
그러니까 줘서 해 될거 없는 옵션

docker run -it --rm --name migolang golang:1.7-alpine go
--rm 옵션은 docker run 을 할 때마다 컨테이너를 생성하는데 이게 매번 지우기가 귀찮을 때가 많다. 그래서 만일 컨테이너가 있다면 자동으로 지우는 옵션. 역시 습관처럼 붙여쓰고 있다.

docker run -it --rm --name migolang golang:1.7-alpine go
--name 옵션은 컨테이너 이름을 지정하지 않으면 지맘대로 임의로 생성한다.
역시 귀찮으니까 지정해서 --rm 옵션으로 지정했다. my > me > mi + golang 해서 migolang 이라고 지었다.
미고랭. 그것은 넘나 맛있는 것. 원래는 Mie goreng이다.

이제 go 소스코드를 작성하고 실행해보자.
package main
import "fmt"
func main() {
  fmt.Printf("Hello, world.\n")
}
hello.go 를 이렇게 만들고 
docker run -it --rm --name migolang golang:1.7-alpine go run hello.go
하면 안될거다 (읭?)
왜냐면 go run은 docker 컨테이너 안에서 실행하고 우리들의 hello.go는 그 바깥에 있기 때문이다.
그러면 현재 hello.go를 docker 컨테이너 않으로 넣어야하는데 -v 옵션으로 서로 연결해주자.
-v "내 경로":"docker 컨테이너 경로" 로 맞춰주자. 현재 경로로 할거고 임의로 docker 컨테이너 안에 /usr/src/myapp (이 경로는 자유롭게) 이란 곳이랑 붙여준다. 
하는 김에 -v 옵션으로 지정한 경로를 go 명령이 실행하는 위치가 되도록 -w 옵션으로 경로를 맞춰주자.
docker run -it -v `echo $PWD`:/usr/src/myapp -w /usr/src/myapp --rm --name migolang golang:1.7-alpine go run hello.go
Hello, world. 가 나오는가? 좋다. 근데 이거 매번 일일이 다 치긴 나는 좀 많이 귀찮다.

alias @="docker run -it -v '$PWD':/usr/src/myapp -w /usr/src/myapp --rm --name migolang golang:1.7-alpine"

go 명령이 시작되는 부분 딱 이전까지 alias로 만들어서 사용하면 편할 것 같다.
@ go run hello.go 해보자.
$ @ go run hello.go
Hello, world.
잘 된다. @ 만 앞에 붙여주면 되니까 편하다.

------------- 절 취 선 -------------

조금 더 욕심을 내서 간단한 웹서버를 하나 띄워보자.
node.js 랑 비슷하게 특정포트를 웹서버로 열어주고 응답을 보내는 예를 만들어서
package mainimport (        "net/http")
func main() {        http.HandleFunc("/", func(res http.ResponseWriter, req *http.Request) {                res.Write([]byte("Hello, world!"))        })        http.ListenAndServe(":8000", nil)}
web.go를 이런 식으로 해보자. 8000 포트를 열고 '/'로 요청이 오면 "Hello, world!"를 출력하는 간단한 예다.
먼저 Dockerfile 을 약간 수정하자.
vi Dockerfile 해서
FROM golang:1.7-alpine
이었던 것에 포트를 노출하기 위해 EXPOSE 를 사용하자
FROM golang:1.7-alpine
EXPOSE 8000
8000번 포트를 노출해주었다.
그리고 alias @도 조금 수정하자.
alias @='docker run -it -v '\''/Users/spectrum/Documents/go/jadeExam/src'\'':/usr/src/myapp -w /usr/src/myapp --rm --name migolang -p 8000:8000 golang:1.7-alpine'
-p 부분을 추가하여 포트 매핑을 해주자 -p <실제포트>:<Docker안에서 Expose한 포트> 순서가 되겠다.
@ docker run web.go
한 뒤, 다른 터미널 하나를 열고 curl http://localhost:8000 해보자.
$ curl localhost:8000
Hello, world!
이렇게 나온다면 승리자.
docker run 커맨드가 너무 길어서 포기하는 경우가 많은데 alias나 sh(혹은 .bat)등을 이용해서 조금만 자동화하면 생각보다 어렵지 않게 쓸 수 있다.

지금은 go get 을 쓰기 위해 Dockerfile 에 git을 포함하여
FROM golang:1.7-alpine
MAINTAINER spectrum <spectrick@gmail.com>
RUN apk --update add git &&\
    rm -rf /var/lib/apt/lists/* && \
    rm /var/cache/apk/*
EXPOSE 8000
이런 식으로 만들고

docker build -t migolang .

이렇게 migolang 이란 이름을 가진 이미지를 생성하여

alias를 마지막으로

alias @="docker run -it -v $PWD:/usr/src/myapp -w /usr/src/myapp --rm --name migolang -p 8000:8000 migolang"

이렇게 migolang 을 지정.
@ go get 을 잘 쓰고 있다. 아주 좋다.

이 블로그의 인기 게시물

Unicode 2.0 에서 한글의 이해

요즘 SNS이나 SNG등등 기계적으로 문장을 생성하는 프로그램들이 넘쳐나는 시대에 의외로 한글처리를 제대로는 프로그램들이 드물구나 하는 생각에 간단한 한글 자소 분석기를 만들어보았다.
링크는 이쪽(http://jsbin.com/ofoqal/10/edit)

애초에 만든 목적은 다음과 같다.
조사처리(은/는, 이/가, 을/를 등등)를 위해 단어의 마지막 글자의 종성을 조사하기 위함인데 예문을 들어보자면

"준기 강남에서 사진 찍었다."
"예슬 홍대에서 식사 했다."
"슬기 대화방에서 나갔습니다."

"준기님은 강남에서 사진님을 찍으셨습니다 고갱님" 이라고 말하면 할말 없다.

한국식 소프트웨어(꼭 소프트웨어가 아니더라도)의 특징이자 장점이 무엇이냐라고 물으면
귀찮을 정도로 깨알같은 디테일이라고 대답할텐데 한글 기계화 작업에 대한 중요성은 프로그램을 만드는 사람들에게도 별로 중요하게 다가오지 않나보다.

에또 사설이 길었다.
한때 우리는 한글코드체계의 비표준 숲속에서 너무도 괴로운 나날들을 보낸 역사가 있다.
KSC5601부터 시작해서 Microsoft통합형한글을 지나 Unicode 2.0의 시대가 왔다.

개인적으로 UTF-8을 사용하지 않고 EUC-KR이나 CP949를 쓰는 제품이나 서비스의 업체의 대표/관계자에게 1억 미만의 벌금 혹은 3년 이하의 금고형의 실형을 내려줬으면 할 정도로 너무나 많은 사람들을 불행하게 하고 막대한 비용을 지출한 악의 근원이라고 생각한다.

하지만 광명이 왔다.
기계적으로 납득이 가능한 검색 및 정렬이 용이한 Unicode 의 시대가 열렸단 말이다.
지금 당신이 복사해서 붙이고 있는 팁들 보다 훨씬 쉽고 명쾌하니 다음 그림을 한번 보자.
(출처:http://www.w3c.or.kr/i18n/hangul-i18n/ko-code.html) 어떤가?
무쟈게 쉽지 않은가?

현대 한글은 초성 19자, 중성 21자, 종성 27자로. 총 19 x 21 x 28 (종성없음 포함…

즐거운 Online Prototyping Tool 들

jsbin, codepen, jsfiddle 이런 것들은 일단 생략. 너무 유명한 것들이라.

https://launchpad.graphql.com - node.js 기반 graphQL 연습장. 이것만으로도 충분히 훌륭한 백엔드
https://codesandbox.io/ npm 사용이 가능한 클라이언트 사이드 연습장. webpackbin이 너무 문제가 많아서 찾아본 것.

https://scrimba.com 이건 codesandbox+ asciinema(https://asciinema.org/) 같은 느낌인데 키 녹화와 음성 녹화 기능이 추가되었다. 다 좋은데 화살표 키로 빨리감기 뒤로감기 기능이 안되고 익스포트(youtube등)으로 지원이 없는게 아쉽다.

이 둘이 만나면? https://codesandbox.io/s/jvlrl98xw3?from-embed
뭐야 이거 무서워 하지마 ㄷㄷ;  graphql+react-native-web(부왘ㅋㅋ)

https://repl.it/languages 전통을 자랑하는 REPL 도구. 지원 언어 종류가 -_-;;;;;

https://tio.run/# repl.it? 장난함? 얘는 지원 언어가 무려 386종류. J랑 아희도 있다.

https://play.golang.org/ 즐거운 go playground. 소스 포멧팅 넘 좋아.

http://decaffeinate-project.org/repl/ 최고의 coffeescript REPL. 원래 용도는 coffee를 ecma6코드로 바꾸는 것이지만...

https://scaphold.io
https://www.graph.cool/ graphql backend service. scaphold.io는 설치도 필요없는 클라우드. graphcool은 호스팅+클라우드 다있음. 둘 다 막상막하. 푸쉬서버도 되고 뭐 미친득.

https://glitch.com/ gomix에서 결국 glitch로 안착.  node.js

https://www.shadertoy.com 잘하고 싶다! 쉐이다! 오디오도 된다!

http:/…

graphql 연습 /w launchpad

https://launchpad.graphql.com/mw9wkzv99
단순 전체쿼리+조건쿼리+추가

http://graphql.org/graphql-js/passing-arguments/
참고. random ID는 crypto 1.0.1 사용
  type Query {
    Members: [member]
    getMember(id: ID!): member
  }
  type member {
    id: ID!
    text: String
  }
  input memberInput {
    text: String
  }
  type Mutation {
    addMember(member: memberInput): member
  } SQL 정의. facebook 쪽은 스트링에 지지는 거 진짜 좋아하네. *.gql 파일이 있다고 하니 이해해주자.
resolver는 var buffer = [];
const resolvers = {
  Query: {
    Members: (root, args, context) => {
      return buffer;
    },
    getMember: (id)=> {
      return buffer.find(o=>o.id)
    }
  },
  Mutation: {
    addMember(_, {member}) {
      const mm = { ...member, id:randomBytes(10).toString('hex') };
      buffer.push(mm);
      return mm;
    }
  }
}; 평범 평범.
https://dev-blog.apollodata.com/tutorial-graphql-subscriptions-server-side-e51c32dc2951 다음으로 pub/sub 연습.
https://launchpad.graphql.com/xvn94n3ql   type Subscription {
    memberAdded: member
  } member가 added되는 순간을 감시. imp…