Commit 503ed60c by anun

add nodejs dockerfile

parent 9507b732
## วิธี set up
ตัวอย่างการ set up makefile ใน docker project
ก่อนใช้งานครั้งแรก ให้แก้ไขไฟล์ release.conf ในแบบเดียวกับข้างล่างนี้ บรรทัดแรก dock.nexpie.com ไม่ต้องแก้, GROUPNAME ตั้งเป็น group ใน gitlab, PROJECTNAME เป็นชื่อ project บน gitlab และ release เป็น revision แก้ได้เลย ไม่มีผลอะไร
```
REGISTRY_HOST=dock.nexpie.com
GROUPNAME=sample
PROJECTNAME=docker-makefile-sample
RELEASE=1.0.0
DEPLOYMENT=sample
PROJECTPATH=.
```
## คำสั่งที่สำคัญ
เวลาจะ build docker image ใช้คำสั่ง
```
make build
```
makefile จะทำการ build และ tag ให้อัตโนมัติ เวลาจะ push image ขึ้น registry บน gitlab ใช้คำสั่ง
```
make push
```
สามารถใช้คำสั่งนี้ในการตรวจสอบว่าโค้ดได้รับการ commit ครบหมดหรือยัง
```
make check-status
```
ดูหมายเลข tag ปัจจุบันของโค้ดใน working repo ของเราได้ด้วยคำสั่งนี้ tag จะเป็นเวอร์ชั่นที่เรากำหนดไว้ ต่อท้ายด้วย revision ของ git ถ้ามีโค้ดที่ไม่ได้รับการ commit ชื่อ tag จะต่อท้ายด้วยคำว่า -dirty แสดงให้รู้ว่ามีการแก้ไขต่อจาก revision นั้น
```
make show-tag
```
## คำสั่งอื่นๆ
ตรวจสอบเวอร์ชั่นของ Makefile ได้จาก
```
make make-version
```
อัพเดตเวอร์ชั่นของ Makefile ให้เป็นเวอร์ชั่นล่าสุดด้วยคำสั่งนี้ โปรแกรมจะทำการดาวน์โหลด Makefile ล่าสุดมาจาก server มาติดตั้งแทนที่ Makefile เดิม อย่าลืม commit Makefile ที่เพิ่งถูกอัพเดตเข้า repo ด้วย
```
make update-make
```
มีคำสั่งช่วยจัดการ docker image สองอันที่ล้อมาจาก docker command คือ make images {patern} แต่จะพิเศษกว่าตรงที่สามารถใส่ filter เพื่อกรองคำได้ เช่น
```
$ make images authhook
dock.nexpie.com/stack/vernemq/authhook 1.0.0-92b23c8 d81e6fad078c 5 days ago 205MB
dock.nexpie.com/stack/vernemq/authhook 1.0.0-e247d15 530f27b0abaf 8 days ago 205MB
dock.nexpie.com/stack/vernemq/authhook 1.0.0-a74eabb 644e4040ee65 11 days ago 205MB
```
และ make rmi {pattern} สำหรับลบ image ที่ตรงกับคำที่ระบุ (ควรใช้อย่างระมัดระวัง ถ้าไม่มั่นใจลองใช้ make images ก่อนเพื่อดูว่าจะมีอันไหนถูกลบบ้าง)
```
$ make rmi authhook
Untagged: dock.nexpie.com/stack/vernemq/authhook:1.0.0-92b23c8
Untagged: dock.nexpie.com/stack/vernemq/authhook@sha256:b6fd7391d568f78a38529992dd2fd6f3ce9d31907b095e87472560898ec0d394
Deleted: sha256:d81e6fad078cc8285f4a575fde93f1f7e31c73b92a70769d73817f3542c2fb0a
Deleted: sha256:bbde04660e22361df77ec58bf7d1aa5098cb30c8d46dc15fe74d35aa4d6cac72
Deleted: sha256:8a62167bbfa2f55190bb8d05cf47c35db5d6d1850a402534f436cd3052535223
Deleted: sha256:7a8637ec88a7af9761f6c5d2bd0afb6ab7685762a31c231e20c36bedc99093cd
Deleted: sha256:927c418ef63c6495adcd11ae32c00b546567fdc67d2d7af16d06a5cd119f3004
Deleted: sha256:e7af038f18fc0e291495352fa9982f28a88109b7a734fc46f6eb90c40d8cc156
Deleted: sha256:a634556f345596e5914b9390ebd29bac67a3c70fe125b47c452bb863c39d0b52
Deleted: sha256:69edd9c969e25844221c1334dd6abf7688f9cc45664df1bd1648e4860586bf4b
Untagged: dock.nexpie.com/stack/vernemq/authhook:1.0.0-e247d15
Untagged: dock.nexpie.com/stack/vernemq/authhook@sha256:6507b4fc8e06b190c21e01eded968b75cb8b9893941e9da3f706db627bcdbceb
Deleted: sha256:530f27b0abaf83f1152f573bc21f9277a241bb99c3fc74a8e8042c4b7c169512
Deleted: sha256:e0bc254cce48c9a18dfc96a8a8f256a3d036959fed1ead53ceb787a5c12896bd
Deleted: sha256:bfb3acaf89cfc49ff3b8504e502c0e204566e664e57064fc02197cf1a49c3f05
Deleted: sha256:e9fb19aa9c655ed03bad49d779ebc28e2c3babaa0c7b242a445f1ad7b0d76229
Deleted: sha256:f5e878e288e6f88ac8c14ac48432e3744a7416f2ed15959c0f5de909d0c0246f
Deleted: sha256:a51dde1cbd8fdea13bbdb113dea4faa4ebf87bee02226cd57f927a3074d00fc5
Deleted: sha256:74a3e1533f8191e8e4b2ae0c96d064493f614ff8b89e8694eeb4f11a9696f01a
Deleted: sha256:8b76aed417658c01058599b637a2b49a4eea01a06c3cb32647a2a91950cf7401
Untagged: dock.nexpie.com/stack/vernemq/authhook:1.0.0-a74eabb
Untagged: dock.nexpie.com/stack/vernemq/authhook@sha256:c7c100347cc631a999ebb363316b57e16d6d5edc9ac3a4b5d68ea9e967c99da1
Deleted: sha256:644e4040ee65ad61e6c337026b8246b496a2128da36d44749102f4476e277945
Deleted: sha256:7f2687ed0f64903cdfe6ef8061c16d8d0f3a8f4e7d325106dbe528b304739123
Deleted: sha256:837756b4ad24424fd75f08b474d020feceafdbab3cf1fbd86f9d83e6e47d08ab
Deleted: sha256:4ea509fdfcb5fbef1ecb2aeab39bb3f410595d96fe575c4cff606916a3f2fd5f
Deleted: sha256:aaf3a21a28a76c809dcb4e82d93d5283dd5e38ab114934133723ff718696ef34
Deleted: sha256:985f9a5c51bbfcc07779ecd3d3a2a7de58795e5def9373708c5d36fc0204aa3f
Deleted: sha256:1489297cdffab45538b0193aa4125a73525b7438a8d841a34647bd070195560c
Deleted: sha256:c3c8a7590bd635fd5c7966a66b9e8a4233c89e144f479ade5417aafbea8291d6
Deleted: sha256:73dc4d83fedb0367801ede826f16281f6f8aeb23fec67f9fe01d7d3fd8a2369e
Deleted: sha256:b08fa9a73b5a8cdcfc04c7244879a3205b45e7109b4581eab047f6af37f935c1
Deleted: sha256:28620184198e6c4d4f8eb9b85ce55f088104b13ac921d1a1e8f40cabe57d7781
Deleted: sha256:0bd1c02508d7694f0920137df038c460baeac9ff2972bc181a619d7cde7e1795
Deleted: sha256:8cf42cb0cb813f59667babe3d94ee2960a5af702427beb053a8306a408301706
```
Microservice ของ NEXPIE มีการใช้ node-config ในการจัดการ configuration ผ่าน environment โดยใช้ไฟล์ config/custom-environment-variables.json
ซึ่งภายในจะมีการกำหนดตัวแปร environment ที่ต้องใช้ไว้ เราสามารถดึงข้อมูลส่วนนี้ออกมาสร้างเป็น env snippet สำหรับใส่ใน yaml ของ deployment ของ kubernetes ได้โดยใช้คำสั่งนี้
(หมายเหตุ ต้องมี jd ติดตั้งอยู่ก่อนเรียกใช้ หากยังไม่มีสามารถติดตั้งได้ด้วยคำสั่ง apt install jd)
```
$ make env-snippet
env:
- name: CER_USERTOKEN_PRIKEY
valueFrom:
secretKeyRef:
name: nexpieconfig
key: cer-usertoken-prikey
- name: CER_DEVICETOKEN_PRIKEY
valueFrom:
secretKeyRef:
name: nexpieconfig
key: cer-devicetoken-prikey
- name: MS_TOKENREGISTRY_PRIKEY
valueFrom:
secretKeyRef:
name: nexpieconfig
key: ms-tokenregistry-prikey
- name: CER_USERTOKEN_PUBKEY
valueFrom:
secretKeyRef:
name: nexpieconfig
key: cer-usertoken-pubkey
```
หากมีการสร้างไฟล์ deployment.yaml ไว้ในโฟลเดอร์ k8s
สามารถสั่ง deploy ขึ้น kubenetes cluster ได้ด้วยคำสั่ง
ในกรณีที่ต้องการระบุ namespace และ context
```
make deploy n=<namespace> c=<context>
```
เช่น
```
make deploy n=nexpie c=minikube
```
ถ้าไม่ได้พิมพ์ -n จะเซตเป็น nexpieio ให้เป็นค่าปกติ แต่ถ้าเซตก็จะใช้ค่าที่เซต ตัวอย่าง สองคำสั่งนี้เท่ากัน
```
make deploy c=dev n=nexpieio
make deploy c=dev
```
ตั้ง annotation ตอน make deploy ได้เลย ตามตัวอย่าง
```
make deploy c=dev a="add user api"
```
ดู deployment history ได้จากคำสั่ง
```
make show-deploy c=dev
```
เซต annotation ของ deploy ล่าสุดบน k8s ได้จากคำสั่งตามตัวอย่าง
```
make annotate c=dev a="add user api"
```
undo deployment ได้จากคำสั่งตามตัวอย่าง
```
make rollback c=dev r=24
```
tag ของ image จะอยู่ในรูปแบบนี้ 1.0.1-1-84f08685
โดยเลขชุดแรก จะได้มาจาก tag ของ git source code
เลขชุดที่สองคือจำนวน commit ที่เกิด หลังจาก git ถูก tag
ชุดที่สาม เป็น hash 8 ตัวแรกของ commit
การ tag ใช้คำสั่งตามตัวอย่างนี้
```
git tag -a 1.0.1 -m "1.0.1"
```
หลังจาก tag local git แล้ว ต้อง push ขึ้น remote ด้วยคำสั่งตามตัวอย่าง
```
git push --follow-tags
```
FROM node:12
WORKDIR /usr/src/app
COPY . .
RUN npm install
# NPM Start
#CMD [ "npm", "run", "prd" ]
# NODE Start
CMD [ "node", "index.js" ]
\ No newline at end of file
# a helper shell script
MAKE_VERSION=1.2.3
define MAKEFUNCTIONCODE
function hasChanges() {
# old version, just track uncommited + untracked files
# test -n "$$(git status -s .)"
# expect 1 to be normal so the untracked file .make-funcition will be ignored
test 0 -ne "$$(git status -s . | sed -e '/.make-function/d' | wc -l)"
}
function getRelease() {
# old : use tag in release.conf
# awk -F= '/^RELEASE=/{print $$2}' release.conf
# new use tag from git of the form -> 1.0.1-2-3b10c420
TAGN=$$(git describe | sed -e "s/-g.*//")
TV=$$(echo $$TAGN | sed -e "s/-.*//")
TM=$$(echo $$TAGN | sed -e "s/^[^\-]*//")
if [ -z "$$TM" ]
then
TM="-0"
fi
echo $$TV$$TM
}
function getBaseTag() {
sed -n -e "s/^tag=\(.*\)$$(getRelease)\$$/\1/p" release.conf
}
function getTag() {
if [ -z "$$1" ] ; then
awk -F= '/^tag/{print $$2}' release.conf
else
echo "$$(getBaseTag)$$1"
fi
}
function setRelease() {
if [ -n "$$1" ] ; then
sed -i.x -e "s/^tag=.*/tag=$$(getTag $$1)/" release.conf
sed -i.x -e "s/^RELEASE=.*/RELEASE=$$1/g" release.conf
rm -f release.conf.x
runPreTagCommand "$$1"
else
echo "ERROR: missing release version parameter " >&2
return 1
fi
}
function runPreTagCommand() {
if [ -n "$$1" ] ; then
COMMAND=$$(sed -n -e "s/@@RELEASE@@/$$1/g" -e 's/^pre_tag_command=\(.*\)/\1/p' release.conf)
if [ -n "$$COMMAND" ] ; then
if ! OUTPUT=$$(bash -c "$$COMMAND" 2>&1) ; then echo $$OUTPUT >&2 && exit 1 ; fi
fi
else
echo "ERROR: missing release version parameter " >&2
return 1
fi
}
function tagExists() {
tag=$${1:-$$(getTag)}
test -n "$$tag" && test -n "$$(git tag | grep "^$$tag\$$")"
}
function differsFromRelease() {
tag=$$(getTag)
! tagExists $$tag || test -n "$$(git diff --shortstat -r $$tag .)"
}
function getVersion() {
result=$$(getRelease)
if hasChanges ; then
result="$$result-dirty"
fi
echo $$result
}
function getVersionWithHash() {
result=$$(getRelease)
if differsFromRelease; then
# output only first 7 characters
# result="$$result-$$(git log -n 1 --format=%h .)"
# output first 8 characters
result="$$result-$$(git log -n 1 --format=%H . | head -c 8)"
fi
if hasChanges ; then
result="$$result-dirty"
fi
echo $$result
}
function nextPatchLevel() {
version=$${1:-$$(getRelease)}
major_and_minor=$$(echo $$version | cut -d. -f1,2)
patch=$$(echo $$version | cut -d. -f3)
version=$$(printf "%s.%d" $$major_and_minor $$(($$patch + 1)))
echo $$version
}
function nextMinorLevel() {
version=$${1:-$$(getRelease)}
major=$$(echo $$version | cut -d. -f1);
minor=$$(echo $$version | cut -d. -f2);
version=$$(printf "%d.%d.0" $$major $$(($$minor + 1))) ;
echo $$version
}
function nextMajorLevel() {
version=$${1:-$$(getRelease)}
major=$$(echo $$version | cut -d. -f1);
version=$$(printf "%d.0.0" $$(($$major + 1)))
echo $$version
}
endef
SHELL=/bin/bash
include release.conf
IMAGE=$(REGISTRY_HOST)/$(GROUPNAME)/$(PROJECTNAME)
VERSION=$(shell . $(RELEASE_SUPPORT) ; getVersion)
VERSIONHASH=$(shell . $(RELEASE_SUPPORT) ; getVersionWithHash)
TAG=$(shell . $(RELEASE_SUPPORT); getTag)
PROJECTPATH?=.
RELEASE_SUPPORT := $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST))))/.make-function
export MAKEFUNCTIONCODE
# If the first argument is "run"...
doit=
ifeq (rmi,$(firstword $(MAKECMDGOALS)))
doit=true
endif
ifeq (images,$(firstword $(MAKECMDGOALS)))
doit=true
endif
ifeq (deploy,$(firstword $(MAKECMDGOALS)))
doit=true
endif
ifeq (show-deploy,$(firstword $(MAKECMDGOALS)))
doit=true
endif
ifeq (annotate,$(firstword $(MAKECMDGOALS)))
doit=true
endif
ifeq (rollback,$(firstword $(MAKECMDGOALS)))
doit=true
endif
ifdef doit
# use the rest as arguments for "make xxx"
#CMD_ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
# ...and turn them into do-nothing targets
#$(eval $(CMD_ARGS):;@:)
ifdef n
DEPLOYARG= -n $(n) --context=$(c)
else
DEPLOYARG= -n nexpieio --context=$(c)
endif
endif
# ifeq ($(CMD_ARGS),)
# else
# EMPTY=
# SPACE=$(EMPTY) $(EMPTY)
# TDARG = $(subst $(SPACE), --context=,$(CMD_ARGS))
# DARG = -n $(TDARG)
# endif
.PHONY: pre-build docker-build post-build build cleanbuild release patch-release minor-release major-release tag check-status check-release showtag show-tag \
push do-push post-push post-init update-make rmi images deploy show-deploy annotate rollback
init:
@echo "$$MAKEFUNCTIONCODE" > ./.make-function
build: init pre-build docker-build post-build
cleanbuild: init pre-build docker-cleanbuild post-build
pre-build:
post-build:
@rm .make-function
post-push:
@rm .make-function
post-init:
@rm .make-function
docker-build:
docker build -t $(IMAGE):$(VERSIONHASH) $(PROJECTPATH)
@DOCKER_MAJOR=$(shell docker -v | sed -e 's/.*version //' -e 's/,.*//' | cut -d\. -f1) ; \
DOCKER_MINOR=$(shell docker -v | sed -e 's/.*version //' -e 's/,.*//' | cut -d\. -f2) ; \
if [ $$DOCKER_MAJOR -eq 1 ] && [ $$DOCKER_MINOR -lt 10 ] ; then \
echo docker tag -f $(IMAGE):$(VERSIONHASH) $(IMAGE):latest ;\
docker tag -f $(IMAGE):$(VERSIONHASH) $(IMAGE):latest ;\
echo docker tag -f $(IMAGE):$(VERSIONHASH) $(IMAGE):$(VERSION) ;\
docker tag -f $(IMAGE):$(VERSIONHASH) $(IMAGE):$(VERSION) ;\
else \
echo docker tag $(IMAGE):$(VERSIONHASH) $(IMAGE):latest ;\
docker tag $(IMAGE):$(VERSIONHASH) $(IMAGE):latest ; \
echo docker tag $(IMAGE):$(VERSIONHASH) $(IMAGE):$(VERSION) ;\
docker tag $(IMAGE):$(VERSIONHASH) $(IMAGE):$(VERSION) ;\
fi
docker-cleanbuild:
docker build --no-cache -t $(IMAGE):$(VERSIONHASH) $(PROJECTPATH)
@DOCKER_MAJOR=$(shell docker -v | sed -e 's/.*version //' -e 's/,.*//' | cut -d\. -f1) ; \
DOCKER_MINOR=$(shell docker -v | sed -e 's/.*version //' -e 's/,.*//' | cut -d\. -f2) ; \
if [ $$DOCKER_MAJOR -eq 1 ] && [ $$DOCKER_MINOR -lt 10 ] ; then \
echo docker tag -f $(IMAGE):$(VERSIONHASH) $(IMAGE):latest ;\
docker tag -f $(IMAGE):$(VERSIONHASH) $(IMAGE):latest ;\
echo docker tag -f $(IMAGE):$(VERSIONHASH) $(IMAGE):$(VERSION) ;\
docker tag -f $(IMAGE):$(VERSIONHASH) $(IMAGE):$(VERSION) ;\
else \
echo docker tag $(IMAGE):$(VERSIONHASH) $(IMAGE):latest ;\
docker tag $(IMAGE):$(VERSIONHASH) $(IMAGE):latest ; \
echo docker tag $(IMAGE):$(VERSIONHASH) $(IMAGE):$(VERSION) ;\
docker tag $(IMAGE):$(VERSIONHASH) $(IMAGE):$(VERSION) ;\
fi
release: check-status check-release build push
push: init do-push post-push
rmi: delete-docker-image
images: list-docker-image
do-push:
docker push $(IMAGE):$(VERSIONHASH)
docker push $(IMAGE):$(VERSION)
docker push $(IMAGE):latest
build-push: build push
show-tag: init release.conf
@. $(RELEASE_SUPPORT); getVersionWithHash
@rm .make-function
showtag: init release.conf
@. $(RELEASE_SUPPORT); getVersionWithHash
@rm .make-function
check-status: init
@. $(RELEASE_SUPPORT) ; ! hasChanges || (echo "ERROR: there are still outstanding changes" >&2) ;
@rm .make-function
check-release: init release.conf post-init
@. $(RELEASE_SUPPORT) ; tagExists $(TAG) || (echo "ERROR: version not yet tagged in git. make [minor,major,patch]-release." >&2 && exit 1) ;
@. $(RELEASE_SUPPORT) ; ! differsFromRelease $(TAG) || (echo "ERROR: current directory differs from tagged $(TAG). make [minor,major,patch]-release." ; exit 1)
update-make: init
@rm Makefile
wget https://dev.nexpie.com/sample/docker-makefile-sample/raw/master/Makefile
@rm .make-function
make-version:
@echo $(MAKE_VERSION)
# awk to cut the column 3, xargs to run command passing arg from pipe
delete-docker-image:
@docker images | grep $(CMD_ARGS) | awk '{print $$3}' | xargs docker rmi || true
# || true to force exoit code to 0 otherwise if no line matched, make will show some error
list-docker-image:
@docker images | grep $(CMD_ARGS) || true
env-snippet:
@jq -r '..|select(type=="string") + "="' config/custom-environment-variables.json > _temp_file_.env
@keg -s nexpieconfig _temp_file_.env > /dev/null
@cat env-snippet-nexpieconfig.yaml
@rm _temp_file_.env
@rm nexpieconfig.yaml
@rm env-snippet-nexpieconfig.yaml
show-deploy: init release.conf
ifndef c
@echo Please run make show-deploy c={context}
else
kubectl rollout history deployment/$(DEPLOYMENT) $(DEPLOYARG)
endif
@rm .make-function
annotate: init release.conf
ifndef c
@echo Please run make show-deploy c={context} a="{annotation text}"
else ifndef a
@echo Please run make show-deploy c={context} a="{annotation text}"
else
kubectl annotate deployment/$(DEPLOYMENT) kubernetes.io/change-cause="$(a)" $(DEPLOYARG)
endif
@rm .make-function
rollback: init release.conf
ifndef r
@echo Please run make rollback r={revision} c={context}
else
kubectl rollout undo deployment/$(DEPLOYMENT) --to-revision=$(r) $(DEPLOYARG)
endif
@rm .make-function
deploy: init release.conf
ifndef c
@echo Deploy failed : Please make deploy with c={context}
else
@cat k8s/deployment.yaml | sed "s/{{IMAGE_TAG}}/$(VERSIONHASH)/g" | kubectl apply -f - $(DEPLOYARG)
@rm .make-function
ifdef a
@kubectl annotate deployment/$(DEPLOYMENT) kubernetes.io/change-cause="$(a)" $(DEPLOYARG)
endif
endif
REGISTRY_HOST=dock.nexpie.com
GROUPNAME=sample
PROJECTNAME=template-dockerfile/nodejs
RELEASE=1.0.0
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment