2020-06-20 20:58:05.855 INFO --- blog.surapong.example.logproblem.api.controller.TestController : TEST_LOG orderId : 5678 BEGIN 2020-06-20 20:58:05.855 INFO --- blog.surapong.example.logproblem.service.OrderService : Complete order orderId : 5678 BEGIN COMPLETE ORDER ORDER 2020-06-20 20:58:05.856 INFO --- blog.surapong.example.logproblem.service.OrderService : Complete order orderId : 5678 Check user userId : a8caf905-4116-44cf-9fc7-572b96b11e96 2020-06-20 20:58:07.850 INFO --- blog.surapong.example.logproblem.api.controller.TestController : TEST_LOG orderId : 1234 BEGIN 2020-06-20 20:58:07.850 INFO --- blog.surapong.example.logproblem.service.OrderService : Complete order orderId : 1234 BEGIN COMPLETE ORDER ORDER 2020-06-20 20:58:07.850 INFO --- blog.surapong.example.logproblem.service.OrderService : Complete order orderId : 1234 Check user userId : c75043d4-064a-4c41-8b5d-549ceee72914 2020-06-20 20:58:09.247 INFO --- blog.surapong.example.logproblem.service.UserService : Check user userId : c75043d4-064a-4c41-8b5d-549ceee72914 BEGIN 2020-06-20 20:58:09.247 INFO --- blog.surapong.example.logproblem.service.UserService : Check user userId : c75043d4-064a-4c41-8b5d-549ceee72914 FINISH 2020-06-20 20:58:09.247 INFO --- blog.surapong.example.logproblem.service.OrderService : Complete order orderId : 1234 END COMPLETE ORDER 2020-06-20 20:58:09.247 INFO --- blog.surapong.example.logproblem.api.controller.TestController : TEST_LOG orderId : 1234 END 2020-06-20 20:58:13.026 INFO --- blog.surapong.example.logproblem.service.UserService : Check user userId : a8caf905-4116-44cf-9fc7-572b96b11e96 BEGIN 2020-06-20 20:58:13.026 INFO --- blog.surapong.example.logproblem.service.UserService : Check user userId : a8caf905-4116-44cf-9fc7-572b96b11e96 FINISH 2020-06-20 20:58:13.026 INFO --- blog.surapong.example.logproblem.service.OrderService : Complete order orderId : 5678 END COMPLETE ORDER 2020-06-20 20:58:13.026 INFO --- blog.surapong.example.logproblem.api.controller.TestController : TEST_LOG orderId : 5678 END
2020-06-20 21:36:53.976 INFO 004E4E7AE9FE47E9BBAAAA5A078608F2 --- blog.surapong.example.logproblem.api.controller.TestController : TEST_LOG orderId : 1234 BEGIN 2020-06-20 21:36:53.976 INFO 004E4E7AE9FE47E9BBAAAA5A078608F2 --- blog.surapong.example.logproblem.service.OrderService : Complete order orderId : 1234BEGIN COMPLETE ORDER ORDER 2020-06-20 21:36:53.976 INFO 004E4E7AE9FE47E9BBAAAA5A078608F2 --- blog.surapong.example.logproblem.service.OrderService : Complete order orderId : 1234Check user userId : 27dc9962-20c8-4f1a-80fa-fe5235baa43f 2020-06-20 21:36:55.262 INFO 6E81515230B941ECAEE47438BE2C9370 --- blog.surapong.example.logproblem.api.controller.TestController : TEST_LOG orderId : 5678 BEGIN 2020-06-20 21:36:55.262 INFO 6E81515230B941ECAEE47438BE2C9370 --- blog.surapong.example.logproblem.service.OrderService : Complete order orderId : 5678 BEGIN COMPLETE ORDER ORDER 2020-06-20 21:36:55.262 INFO 6E81515230B941ECAEE47438BE2C9370 --- blog.surapong.example.logproblem.service.OrderService : Complete order orderId : 5678 Check user userId : 7d6ca7e1-4dfa-4aee-9f75-93eb451fbeab 2020-06-20 21:36:59.203 INFO 004E4E7AE9FE47E9BBAAAA5A078608F2 --- blog.surapong.example.logproblem.service.UserService : Check user userId : 27dc9962-20c8-4f1a-80fa-fe5235baa43f BEGIN 2020-06-20 21:36:59.203 INFO 004E4E7AE9FE47E9BBAAAA5A078608F2 --- blog.surapong.example.logproblem.service.UserService : Check user userId : 27dc9962-20c8-4f1a-80fa-fe5235baa43f FINISH 2020-06-20 21:36:59.203 INFO 004E4E7AE9FE47E9BBAAAA5A078608F2 --- blog.surapong.example.logproblem.service.OrderService : Complete order orderId : 1234 END COMPLETE ORDER 2020-06-20 21:36:59.203 INFO 004E4E7AE9FE47E9BBAAAA5A078608F2 --- blog.surapong.example.logproblem.api.controller.TestController : TEST_LOG orderId : 1234 END 2020-06-20 21:37:01.167 INFO 6E81515230B941ECAEE47438BE2C9370 --- blog.surapong.example.logproblem.service.UserService : Check user userId : 7d6ca7e1-4dfa-4aee-9f75-93eb451fbeab BEGIN 2020-06-20 21:37:01.167 INFO 6E81515230B941ECAEE47438BE2C9370 --- blog.surapong.example.logproblem.service.UserService : Check user userId : 7d6ca7e1-4dfa-4aee-9f75-93eb451fbeab FINISH 2020-06-20 21:37:01.167 INFO 6E81515230B941ECAEE47438BE2C9370 --- blog.surapong.example.logproblem.service.OrderService : Complete order orderId : 5678END COMPLETE ORDER 2020-06-20 21:37:01.167 INFO 6E81515230B941ECAEE47438BE2C9370 --- blog.surapong.example.logproblem.api.controller.TestController : TEST_LOG orderId : 5678 END
จะเห็นว่าหลัง INFO จะมีเลขยาวๆโผล่ขึ้นมา ซึ่งเลขนี้เป็นเลข ID ของแต่ละ Request นั่นเองคราวนี้เราสามารถ Grep log ด้วยเลข ID นี้ ทำให้ได้ Log ที่เกี่ยวข้องกับ Request นี้ทั้งหมด
โดยจากตัวอย่างไฟล์เราจะสร้าง container ที่เป็น DB ขึ้นมาสองตัว โดยตัวนึง Bind ที่ Port 3306 อีกตัวที่ Port 3307 โดยเราสามารถดูผลลัพธ์การสร้างได้ด้วยคำสั่ง
จะเห็นว่าจากต้อง run 5 command กลายเป็นเขียนไฟล์ config กำหนด แล้วกด run คำสั่งเดียว เขียนเสร็จแล้วสามารถ share ไปให้คนอื่นใช้ต่อได้ด้วย โดยไม่ต้องกลัวว่าอีกเครื่องจะ run script ได้ไหม ขอแค่เครื่องนั้น ลง docker-compose ก็พอ
Install docker compose กันก่อน
วิธีลง docker-compose นั้นมีวิธีบอกอยู่แล้วแถมเป็น official ด้วย โดยสามารถดูได้ตามนี้เลย https://docs.docker.com/compose/install/ โดยใครใช้ OS อะไรก็ใช้แบบนั้นที่เขาแนะนำได้เลย
จากนั้นทำการสั่งย้าย current directory ไปอยู่ที่เดียวกับที่ไฟล์ docker-compose.yml อยู่จากนั้นสั่ง
1
docker-compose up
บนหน้าจอจะขึ้นประมาณนี้จะเห็นว่ามันคล้ายๆสั่ง docker run เลยแต่มีสีสันเพิ่มเข้ามา
อธิบาย docker-compose.yml
จริงๆถ้าใครเคยสั่ง docker run จนชิน พอมาเห็นไฟล์ docker-compose.yml จะเข้าใจทันทีเลยว่าจะเปลี่ยนจาก docker run เป็น docker-compose.yml ยังไงโดยแทบไม่ต้องอธิบายเลย
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
version:'3' # ตรง version คือบอกว่าเราใช้ docker-compose file version อะไร อันนี้มีผลมากนะครับเพราะบาง # config จะมาใน version ใหม่ๆ บาง config ก็ถูกยกเลิกใน version ใหม่
services : # ส่วนนี้คือการบอกว่าถึงส่วนที่จะ config บอกว่าต้อง run container อะไรบ้าง
เรามาลองสร้าง web application จากภาษา go กัน อันนี้เลือกภาษา go เพราะมันต้อง compile code จริงๆอยากจะเขียนภาษา Java แต่เดี๋ยวมันจะงงเพราะมีพิธีกรรมมากมายเลยเอาภาษา go ละกันไฟล์เดียวจบเลยจะได้เป็นตัวอย่างง่ายๆ
ตัว Source code นี้ไม่มีอะไรมากไปกว่ารับเปิด Port 8080 แล้วแสดงข้อมูลออกทางหน้าจอ คราวนี้ลอง run โปรแกรมดูครับ ถ้าเครื่องภาษา go run server.go ครับ
จากนั้นสร้าง Dockerfile ขึ้นมาครับ
1 2 3 4 5 6 7 8 9 10
FROM golang:rc-buster
WORKDIR /app ADD server.go /app
# เป็นคำสั่งที่ใช้ในการ compile source code ให้กลายเป็น binary file ที่สามารถสั่ง run ได้เลย RUN RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .
docker run --rm test_change_cmd ls docker run --rm test_entrypoint ls
คราวนี้ไม่ Error ทั้งคู่ โดยฝั่ง CMD จะใช้คำสั่ง ls ซึ่งทำการ list file and directory ในปัจจุบันออกมา ส่วนฝั่ง ENTRYPOINT ยังคงเป็นการ echo คำออกมาแต่เป็นการเปลี่ยนเป็น hello world Matilda ls
แล้วจะใช้อะไร
ถ้าเอาง่ายๆก็คือ ถ้าใช้ CMD คือเราอยากให้ Container ที่ Run จาก Image นั้น run คำสั่งที่เหมือนกันไม่ต้องมีการ Customize ตัวคำสั่งที่อยาก run เช่นอย่าง image httpd นี้เขาใช้ CMD คือเขาอยากให้ Image นี้ run ด้วยคำสั่ง httpd-foreground เท่านั้น ส่วนการ config อื่นๆให้ไปทำกันที่ Environment หรือการ mount volume file config เอา แต่ถ้าใช้ ENTRYPOINT อันนี้คือเขาต้องการให้สามารถ customize คำสั่งตอน run container ได้ประมาณว่า run โดยใช้ parameter อะไรบ้างเป็นต้น โดยเขาจะใช้วิธีการสร้างไฟล์ .sh ขึ้นมาสักตัว ประมาณนี้ โดยตัวอย่างเราจะทำเป็นไฟล์ชื่อ entrypoint.sh จากนั้นในไฟล์ entrypoint ก็รับ parameter เข้ามาเพื่อให้ทำอะไรบางอย่าง เช่นตัวอย่างผมจะรับ parameter เข้ามาเพื่อทำอะไรบางอย่างที่แตกต่างกันเช่น
ไฟล์ entrypoint.sh
1 2 3 4 5 6 7 8 9 10 11 12 13 14
if [ "$1" = "" ] then echo"Case no parameter" elif [ "$1" = "infinity" ] then echo"Case run infinity loop" while : do echo"IN LOOP" sleep 1 done else echo"Case other" fi