Docker references

Docker references

·

12 min read

Tại sao phải dùng Docker ?

Việc setup và deploy application lên một hoặc nhiều server rất vất vả từ việc phải cài đặt các công cụ, môi trường cần cho application đến việc chạy được ứng dụng chưa kể việc không đồng nhất giữa các môi trường trên nhiều server khác nhau. Chính vì lý do đó Docker được ra đời để giải quyết vấn đề này.

Docker là gì ?

Docker là một nền tảng cho developers và sysadmin để develop, deploy và run application với container. Nó cho phép tạo các môi trường độc lập và tách biệt để khởi chạy và phát triển ứng dụng và môi trường này được gọi là container. Khi cần deploy lên bất kỳ server nào chỉ cần run container của Docker thì application của bạn sẽ được khởi chạy ngay lập tức.

Lợi ích của Docker

  • Không như máy ảo Docker start và stop chỉ trong vài giây.
  • Bạn có thể khởi chạy container trên mỗi hệ thống mà bạn muốn.
  • Container có thể build và loại bỏ nhanh hơn máy ảo.
  • Dễ dàng thiết lập môi trường làm việc. Chỉ cần config 1 lần duy nhất và không bao giờ phải cài đặt lại các dependencies. Nếu bạn thay đổi máy hoặc có người mới tham gia vào project thì bạn chỉ cần lấy config đó và đưa cho họ.
  • Nó giữ cho word-space của bạn sạch sẽ hơn khi bạn xóa môi trường mà ảnh hưởng đến các phần khác.

Cách cài đặt

Hãy cài đặt Docker tương ứng môi trường của bạn tại đây. Chọn bản cài đặt tương ứng với hệ điều hành của bạn và tiến hành cài đặt theo hướng dẫn đối với Linux còn Windows và MacOS thì bạn chỉ cần tải bản cài về và cài đặt như mọi application khác. Sau khi cài đặt xong để kiểm tra xem cài đặt thành công hay không ? Mở command line:

$ docker version
$ docker info
$ docker run hello-world

Một số khái niệm

99c936d5-36dc-4928-921a-30e1b4338983.webp

  • Docker Client: là cách mà bạn tương tác với docker thông qua command trong terminal. Docker Client sẽ sử dụng API gửi lệnh tới Docker Daemon.
  • Docker Daemon: là server Docker cho yêu cầu từ Docker API. Nó quản lý images, containers, networks và volume.
  • Docker Volumes: là cách tốt nhất để lưu trữ dữ liệu liên tục cho việc sử dụng và tạo apps.
  • Docker Registry: là nơi lưu trữ riêng của Docker Images. Images được push vào registry và client sẽ pull images từ registry. Có thể sử dụng registry của riêng bạn hoặc registry của nhà cung cấp như : AWS, Google Cloud, Microsoft Azure.
  • Docker Hub: là Registry lớn nhất của Docker Images ( mặc định). Có thể tìm thấy images và lưu trữ images của riêng bạn trên Docker Hub ( miễn phí).
  • Docker Repository: là tập hợp các Docker Images cùng tên nhưng khác tags. VD: golang:1.11-alpine.
  • Docker Networking: cho phép kết nối các container lại với nhau. Kết nối này có thể trên 1 host hoặc nhiều host.
  • Docker Compose: là công cụ cho phép run app với nhiều Docker containers 1 cách dễ dàng hơn. Docker Compose cho phép bạn config các command trong file docker-compose.yml để sử dụng lại. Có sẵn khi cài Docker.
  • Docker Swarm: để phối hợp triển khai container.
  • Docker Services: là các containers trong production. 1 service chỉ run 1 image nhưng nó mã hoá cách thức để run image — sử dụng port nào, bao nhiêu bản sao container run để service có hiệu năng cần thiết và ngay lập tức.

Dockerfile

Dockerfile là file config cho Docker để build ra image. Nó dùng một image cơ bản để xây dựng lớp image ban đầu. Một số image cơ bản: python, unbutu and alpine. Sau đó nếu có các lớp bổ sung thì nó được xếp chồng lên lớp cơ bản. Cuối cùng một lớp mỏng có thể được xếp chồng lên nhau trên các lớp khác trước đó.

FROM

FROM <image> [AS <name>]

or

FROM <image>[:<tag>] [AS <name>]

or

FROM <image>[@<digest>] [AS <name>]
  • Các bạn có thể hiểu đơn giản, đây là thằng trung tâm mà bạn sẽ sử dụng nó làm cái base cho các action ở phía sau. Một Dockerfile hợp lệ phải bắt đầu bằng lệnh FROM. Bạn có thể sử dụng các images của mình tạo ra, hoặc có thể sử dụng hình ảnh do đồng nghiệp trong team tạo sẵn, hoặc đơn giản hơn là nó được chính thằng Docker build lên.
  • FROM có thể xuất hiện nhiều lần trong 1 Dockerfile để tạo nhiều ảnh hoặc sử dụng trong 1 giai đoạn build khác nhau. VỚi mỗi lệnh FROM, sẽ xóa đi trạng thái của FROM được tạo ra ở trước đó.
  • Tag và digest là các tùy chọn của image, mặc định nếu không có tag thì nó sẽ lấy version cuối cùng: latest. Example: FROM ubuntu:16:04 AS ubuntu Ở đây, mình đang sử dụng images được Docker build lên có tên là ubuntu, với tag là 16.04, và mình đặt cho nó một cái định danh ngắn gọn là ubuntu. Có một từ khóa nữa mà chắc bạn sẽ gặp nó ở đâu đó rồi, vì nó là thằng duy nhất có thể đứng trước FROM trong Dockerfile, đó là ARG.
  • ARG thường khai báo các giá trị của biến hỗ trợ cho quá trình build từ FROM. Thường là khai báo tag của image mà mình muốn sử dụng:
ARG  CODE_VERSION=16.04
FROM ubuntu:${CODE_VERSION}
CMD  /code/run-app

RUN

Với câu lệnh RUN, có 2 forms cho các bạn lựa chọn:

RUN <command>

(shell form, command được chạy bên trong shell, mặc định là /bin/sh -c trên Linux or cmd /S /C trên Windows). or

RUN ["executable", "param1", "param2"]

(exec form)

  • Lệnh RUN sẽ thực hiện bất kỳ lệnh nào trên layer của image hiện tại và hiển thị kết quả. Kết quả của nó thường sẽ được sử dụng cho bước tiếp theo trong Dockerfile.
  • Việc phân lớp các lệnh RUN và tạo ra các commit theo các concepts của Docker, nới có các commit dễ dàng và các container có thể được tạo từ một số điểm trong lịch sử của image, giống như kiểm soát nguồn.
  • Shell mặc định cho form shell có thể thay đổi bằng cách sử dụng lệnh SHELL.
  • Trong shell, bạn có thể sử dụng .\ để tiếp tục RUN trên câu lệnh RUN trong dòng tiếp theo trên cùng một line. Ví dụ:
    RUN /bin/bash -c 'source $HOME/.bashrc; \
    echo $HOME'
    
    Chúng cùng lúc được chạy trên một dòng
RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME'

CMD

VỚi CMD, có 3 forms cho việc thực hiện:

CMD ["executable","param1","param2"]

(hình thức exec, đây là hình thức được mọi người ưa thích sử dụng).

CMD ["param1","param2"]

(là tham số mặc định cho ENTRYPOINT).

CMD command param1 param2

(shell form).

  • Trong mỗi Dockerfile chỉ được có duy nhất một câu lệnh CMD. Nếu bạn sử dụng nhiều hơn 1 câu lệnh CMD thì chỉ có câu lệnh CMD cuối cùng được chạy.
  • Mục đích chính của CMD là cung cấp lệnh chạy mặc định cho 1 container. Những điều mặc này có thể bảo gồm một câu lệnh thực thi, hoặc chúng có thể bỏ qua các câu lệnh thực thi, trong trường hợp đó bạn cũng phải chỉ định một lệnh ENTRYPOINT.
  • Khi bạn sử dụng hình thức shell cho lệnh CMD, thì <command> sẽ thực thi với /bin/sh - c:
    FROM ubuntu
    CMD echo "This is a test CMD."
    
  • Còn nêu bạn không muốn chạy <command> với sherll thì bạn cần phải trình bày đầy đủ câu lệnh với đường dẫn chi tiết như mảng JSON:
    FROM ubuntu
    CMD ["/usr/bin/wc","--help"
    
    Còn nếu bạn không muốn container của bạn chạy 1 câu lệnh trong các lần sử dụng, bạn có thể xem xét việc sử dụng ENTRYPOINT bên với câu lệnh CMD

MAINTAINER

MAINTAINER <name>

Đây là một option giúp cho bạn có thể biết ai là người viết và build lên images cho mình sử dụng.

MAINTAINER LIEN KET CUA TOI

ADD

Có 2 hình thức sử dụng:

ADD <src>... <dest>

or

ADD ["<src>",... "<dest>"]

(hình thức này yêu cầu cho các đường dẫn chứa khoảng trắng).

  • ADD sẽ sao chép các files, thư mục hoặc remote của file từ URLs từ <src> và thêm vào hệ thống tệp của hình ảnh ở đường dẫn <dest>.
  • Nhiều tài nguyên <src> có thể được chỉ định nhưng nếu chúng là các tệp hoặc thư mục thì chúng phải tương đối so với thư mục nguồn đang được xây dụng.
  • Mỗi <src> có thể chứa ký tự đạị diện và kết hợp sẽ được thực hiện bằng cách sử dụng luật Go's filepath.Match:
    ADD test relativeDir/          # adds "test" to `WORKDIR`/relativeDir/
    ADD test /absoluteDir/         # adds "test" to /absoluteDir/
    
  • Khi thêm tệp hoặc thư mục chứa các ký tự đặc biệt (như [ và ]), cần phải thoát khỏi những đường dẫn theo nguyên tắc Golang để ngăn chúng không được coi như là mẫu phù hợp. VD: để thêm file có tên là arr[0].txt, sử dụng như sau:
    ADD arr[[]0].txt /mydir/    # copy a file named "arr[0].txt" to /mydir
    

EXPOSE

EXPOSE <port> [<port>/<protocol>...]

Lệnh EXPOSE thông báo cho Docker cho container lắng nghe trên các cổng mạng được chỉ định khi chạy. Bạn có thể chỉ định cổng lắng nghe TCP hay UDP, và mặc định của nó sẽ là TCP nếu giao thức không được chỉ định. Lệnh EXPOSE không thực sự publish cổng. Nó hoạt động như một loại tài liệu hướng dẫn giữa người xây dựng images và người chạy container, về những cổng nào dự định được published. Để thực sự publish cổng khi chạy container, sử dụng -p để cho phép docker chạy và map đến một hoặc nhiều cổng, hoặc -P để cho phép nó tạo các cổng và map chúng tới các cổng cao cấp. Để thiết lập chuyển hướng cổng trên hệ thống máy chủ, sử dụng option -P. Lệnh docker network hỗ trợ tạo ra các mạng cho việc truyền thông giữa các container mà không cần phải publish cổng hoặc hiển thị, bới bì container kết nối đến mạng có thể giao tiếp với nhau qua bất kì cổng nào. Đây là một phần ứng dụng khá hay của Docker cho phép các kỹ sư mạng, mình sẽ tìm hiểu nó chi tiết hơn trong 1 bài viết sắp tới!!!!.

COPY

COPY có hai forms chính cho bạn sử dụng:

COPY <src>... <dest>

or

COPY ["<src>",... "<dest>"]

(hình thức này yêu cầu cho các đường dẫn có chứa khoảng trắng).

  • COPY sao chép các tệp tin hoặc thư mục từ <src> và thêm chúng vào hệ thống tệp tin của container ở đường dẫn .
  • Nhiều tài nguyên từ <src> có thể được chỉ định nhưng chúng phải liên quan với thư mục nguồn đang được xây dựng (bối cảnh của việc xây dựng).
  • Với mỗi <src> có thể chứa ký tự đại diện và kết hợp sẽ được thực hiện bằng sử dụng luật Go's filepath.Match. Ví dụ:
    COPY hom* /mydir/        # sao chép tất ccác tệp tin có tên bắt đầu bằng "hom" vào thư mực mydir
    COPY hom?.txt /mydir/    # ? được thay thế bằng bất kỳ ký tự đơn, ví dụ., "home.txt"
    
  • <dest> là một đường dẫn tuyệt đối, hoặc một path liên quán đến WORKDIR, trong đó resource sẽ được sao chép bên trong container đích.
    COPY test relativeDir/   # sao chép "test" vào `WORKDIR`/relativeDir/
    COPY test /absoluteDir/  # sao chép "test" to /absoluteDir/
    
  • Khá giống với ADD, khi sao chép các tệp tin hoặc thư mục có các ký tự đặc biệt, cần phải escape những đường dẫn theo quy tắc Golang để ngăn chúng khỏi bị hiểu nhầm như một mẫu phù hợp. Ví dụ tệp tin có têm là arr[0].txt, sử dụng như sau:
    COPY arr[[]0].txt /mydir/    # sao chép tệp tin có tên "arr[0].txt" vào /mydir/.
    

VOLUME

Command: VOLUME ["/data"] 93bcf53e-5a17-441d-b989-dd0611ea805c.webp Lệnh VOLUME tạo ra một điểm kết nối với tên được chỉ định và đánh dấu nó như là giữ các khối được gắn từ bên ngoài máy chủ lưu trữ hoặc từ các container khác. Giá trị có thể là mảng JSON, VOLUME ["/var/log"], hoặc một chuỗi với nhiều đối số, giống như VOLUME /var/log hoặc VOLUME /var/log /var/db. Để hiểu thêm về nó, hoặc các ví dụ đơn giản, bạn có thể xem tại Share Directories via Volumes Lệnh chạy docker docker run khởi tạo số lượng mới được tạo ra với bất kỳ dữ liệu nào tồn tại tại vị trí được chỉ định bên trong image cơ sở. Ví dụ:

FROM ubuntu
RUN mkdir /myvol
RUN echo "hello world" > /myvol/greeting
VOLUME /myvol

Kết quả của Dockerfile trong image được tạo ra khi docker run, một điểm mới được tạo ra /myvol và sao chép tệp tin greeting vào trong volume vừa được tạo.

ENTRY POINT

Với ENTRY POINT có hai hình thức sử dụng chính:

ENTRYPOINT ["executable", "param1", "param2"]

(hình thức thực thi, được nhiều người sử dụng). or

ENTRYPOINT command param1 param2

(hình thức shell).

  • ENTRYPOINT cho phép cấu hình container sẽ chạy như một tệp tin thi hành. Ví dụ: start nginx với nội dung mặc định, lắng nghe trên cổng 80:
    docker run -i -t --rm -p 80:80 nginx
    

    NOTE: cũng giống như CMD, mỗi một tệp Dockerfile cũng chỉ có một câu lệnh ENTRYPOINT có hiệu lực.

WORKDIR

Command:

WORKDIR /path/to/workdir

WORKDIR thiết lập thư mục làm việc cho các lệnh RUN, CMD, ENTRYPOINT, COPYADD nào nằm trong Dockerfile. Nếu WORKDIR không tồn tại, nó sẽ được tạo ra ngay cả khi nó không được sử dụng trong bất kỳ lệnh Dockerfile tiếp theo nào. WORKDIR có thể sử dụng nhiều lần trong Dockerfile. Nếu đường dẫn được cung cấp là tương đối, nó sẽ tương ứng với đường dẫn của lệnh WORKDIR trước đó. Ví dụ:

WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd

Đầu ra của lệnh pwd cuối cùng trong Dockerfile này sẽ là /a/b/c. WORKDIR có thể giải quyết các biến môi trường được đặt trước bằng ENV. Chỉ có thể sử dụng các biến môi trường được đặt rõ ràng trong Dockerfile.

ENV DIRPATH /path
WORKDIR $DIRPATH/$DIRNAME
RUN pwd

Đầu ra của lệnh pwd cuối cùng trong tệp Dockerfile này sẽ là /path/$DIRNAME.

Trên đây mình giới thiệu một số lệnh của Dockerfile được sử dụng khá thông dụng trong quá trình tạo Dockerfile. Tuy chưa đầy đủ nhưng với những lệnh này, nếu nắm rõ chúng thì việc thiết lập môi trường phát triển ứng dụng khá là dễ dàng.