기본 콘텐츠로 건너뛰기

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 을 잘 쓰고 있다. 아주 좋다.

이 블로그의 인기 게시물

meteor로 nw.js 개발하기.

실제로 nw.js 어플리케이션을 개발하다보면 UI구현하기 막막하고 수동으로 리프레쉬 하는 것도 귀찮아서 Meteor 연동을 하려고 했더니 생각보다 간단했다.

디렉토리 구조는 먼저 이렇게 잡았다.
`- app
  `-client
  `-public
`- dist
  `- 배포용 html,css,js
  `- package.json
`- package.json 아이디어는 이렇다. nw.js의 시작페이지를 http://localhost:3000으로 두고 배포시엔 meteor client 배포툴인 meteor-build-client를 사용하여 html,css,js 로 분리하는 계획이다.

가장 중요한 nw.js 용 package.json 파일은 아래와 같이 구성한다.
{
  "main": "http://localhost:3000",
  "node-remote": "http://localhost:3000",
  "name": "<앱이름>"
} 이게 전부. 어떻게 보면 Web과 nw.js를 동시에 개발할 수도 있는 환경이기도 한 것이다.
meteor create app 을 해서 meteor용 앱을 만들고 meteor 를 시작한다.
그리고, 위의 package.json이 있는 경로로 돌아가서 nw . 으로 nwjs를 실행한다.

한번 번쩍하더니 잘 된다.
cordova 등에서 index.html 대신 http://localhost:3000을 하는 것도 비슷한 느낌이다.

즐겁게 개발을 일단 마구 하고 실제로 배포하기 위해서는 개발환경이 아니라 html,css,js로 구성된 배포본을 만들어야한다.
npm install -g 해도 되지만 어짜피 Meteor에서만 쓸거
meteor npm install -g meteor-build-client 해버릴거다.

개발은 문제 없어 보이고 배포판을 한번 만들어보자. meteor app 이 있는 경로(meteor run으로 …

RxJS - ReactiveX 인터뷰

A: 왜 RxJS입니까
B: javascript는 참 쉽고 친숙한 언어죠.
A: 별로 그렇게 생각 안합니다만.
B: 그래서 좀 어렵고 있어보이는게 뭘까 싶어서...
A: 네?
B: 함수형이라는게 유행하기도 하고
f(x) 좋쟎습니까? 미스테리~ 미스테리~ 정수정짱짱 으아아

이런 수학선생님이라면 수포자 따윈 A: ...
B: 그리고 반응형이라는 말 뭔가
A: 뭔가?
B: 대충대충해도 막 알아서 할거 같고...
A: 그럴리가요?
B: 안그렇겠죠?
A: 네
B: 네

(잠시만 기다려주세요)

A: 그래도 뭔가 매력이 있으니 이렇게 시간을 내셔서 이것저것 Rx에 대해 글도 쓰고 이야기도 하고 그러시는거 아닌가요?
B: 매력이라.
으음.
제가 팔꿈치 터널 증후근이 좀 있어요.
오른손 세끼손가락, 약지손가락이 저립니다.
A: 무슨 상관이?
B: 그래서 각종 괄호를 쓰는게 너무 힘듭니다.
소중대괄호 만든 사람 죽었으면.
Hello world (ASCII): https://esolangs.org/wiki/Parenthesis_Hell
A: 이미 옛날에 돌아가셨겠죠.
B: 그렇겠네요.
아무튼 그래서 소중대괄호 의존이 적은 커피스크립트를 쓰는데요.
A: 빨리 본론을 말씀해주시죠.
B: 커피스크립트에서 가로로 80자 이상쓰면 Line exceeds maximum allowed length 라고 경고해요.
A: 그래서요?
B: 근데 Rx를 쓰면 코드를 가늘게 쓸 수가 있더라구요.
A: 호오?
B: 그리고 = 쓰는 것도 너무 힘듭니다.
A: 네?
B: 오른손을 쓰쟎아요.
A: ...
그러니까 정리하면
1. 괄호가 힘들다
2. 커피를 쓴다
3. 커피는 길게 쓰면 경고
4. Rx를 쓰면 코드가 가늘다
5. 대입문을 줄이고 싶다.
B: 네
하지만 5번은 생각보다 별로...
A:
B:

B: 아!
A: ?
B: 코드가 가늘어서 좋은 점이.
A: 네.
B: 핸드폰에서 코드를 보기 좋습니다.
A: ... 왜 팔꿈치 터널 증후근이 안 낫는지 알겠습니다.
B: 도와주세요.
쇠고기 사묵으면 나을 것 같습니…

Troubleshooting - Meteor package가 적용이 되지 않을 때

버전 1.5 기준 package.js에서 Package.onUse 에 새 패키지를 추가했는데 인식하지 못하는 경우가 있다.
Package.onUse((api) => {
  api.use([
    'vulcan:core',
    'vulcan:forms',
    'vulcan:accounts' /* <-- 추가함! */
  ]);
...
} 내부패키지건 원격패키지건 안되는 안된다. 이럴 때 meteor add 후 meteor remove 해도 되지만 더 간단한 방법이 있다. meteor update vulcan:accounts 이렇게 update 해주는 방법이 있다. .meteor/package 파일을 건들지 않아서 좋다. 그래도 역시 좋지 않다. Meteor 스럽지 않다. https://github.com/meteor/meteor/issues/7721 현재 1.5.2에서도 해결이 안되었군요. 해결되어 적용되면 다시 글 올리겠습니다.