+300

Docker: Chưa biết gì đến biết dùng (Phần 2 - Dockerfile)

1. Mở đầu

Xin chào các bạn, ở bài trước Docker: Chưa biết gì đến biết dùng (Phần 1):

  • Chúng ta đã cùng nhau tìm hiểu công nghệ ảo hóa containerlization với công cụ docker của công ty cùng tên. Tuy nhiên nội dung chủ yếu tập trung vào lý thuyết vào lịch sử và cơ chế hoạt động.

  • Hôm nay, chúng ta sẽ đi sâu hơn để khám phá cách sử dụng Docker trong thực tế.

  • Như bác Hoàng Nam Tiến từng nói:

    Hãy nhớ rằng Tiếng Anh là ngôn ngữ để làm việc , để sống, không còn là ngoại ngữ nữa.
    
  • Thì Docker hiện tại gần như đã trở thành tiêu chuẩn trong phát triển phần mềm, không chỉ xuất phát từ sự tiện lợi, mà còn bởi cách nó thay đổi tư duy, quy trình và phương pháp làm việc.

  • Nên nếu như bạn chưa dùng Docker thì câu hỏi không phải là Tại sao nữa mà là Làm thế nào để bắt đầu. Chuỗi bài viết này sẽ hỗ trợ bạn giải quyết phần nào câu hỏi đó.

  • Trước khi đọc phần 2, đừng quên đọc lại phần 1 - để mình hiểu rõ lý thuyếtbản chất của Docker đã nhé.

Let's go ! 👋👋👋

2. Source code

Bớt lý thuyết lại, coding luôn:

Dưới đây là cấu trúc demo source code của chúng ta:

image.png

  • Thư mục web_app:

    • Đây là nơi chứa mã nguồn chương trình của bạn.

    • Nó có thể là một ứng dụng viết bằng PHP, Node.js hoặc Python ...

    • Trong ví dụ này, để cho đơn giản, ta chỉ tạo file index.html với nội dung:

      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <title>Docker tutorial</title>
      </head>
      <body>
          <div>Hello World</div>
      </body>
      </html>
      

      Sẽ hiển thị dòng Hello World khi chạy trên trình duyệt.

    • Trong quá trình phát triển, bạn có thể chỉnh sửa mã nguồn trong thư mục này trực tiếp trên máy thật (host OS) bằng các trình soạn thảo như VS Code.

    • Nhờ docker volume, những thay đổi sẽ ngay lập tức được cập nhật vào bên trong container, kết hợp với hot reload để hiển thị kết quả tức thì. Ví dụ sửa text Hello World thành Hello World From Asia.

  • Dockerfile:

    • Như đã tìm hiểu, file này định nghĩa cách tạo docker image.
    • Sau khi build được image, bạn có thể khởi tạo container - đây chính là môi trường ảo hoá để chạy ứng dụng ở bên trong.
  • File start.sh:

    • Đây là script chứa những câu lệnh được thực thi mỗi khi container khởi động.
    • Có thể dùng script này để khởi chạy các dịch vụ như MySQL, Nginx, Redis, ...

3. Dockerfile là gì ?

  • Dockerfile:

    • Một file dạng text thuần tuý.
    • Không có đuôi mở rộng (như .txt, .sh ...) mà docker nhận diện nó thông qua tên Dockerfile cố định.
    • Gồm các lệnh được viết tuần tự, hướng dẫn Docker xây dựng docker image mà bạn muốn.
  • Có thể liên tưởng tới việc cài lại hệ điều hành:

    • Khi cài lại Windows:
      • Bạn dùng usb boot để cài os lên laptop.
      • Sau đó cài các phần mềm lên như Chrome, VS code, ...
    • Thì khi build docker images từ Dockerfile cũng tương tự:
      • Bạn cũng bắt đầu từ một base image ví dụ: ubuntu, centos ...

      • Sau đó thêm các lệnh cài đặt, sao chép hoặc cấu hình.

         # Use the official Ubuntu image as the base
         FROM ubuntu:latest
        
         # Configure the main working directory
         WORKDIR /app
        
         # Update package lists and install necessary packages
         RUN apt-get update; \
             apt-get install -y --no-install-recommends \
                 nginx \
                 nano \
                 vim \
                 postgresql; \
             apt-get clean; \
             rm -rf /var/lib/apt/lists/*
        
         # Copy the startup script and set permissions
         COPY start.sh .
         RUN chmod +x ./start.sh
        
         # Set the entrypoint
         ENTRYPOINT ["./start.sh"]
        
         # Expose the required port
         EXPOSE 80
        
        
    • Như việc xây một bức tường:

image.png

4. Cách viết Dockerfile

Các câu lệnh trong Dockerfile được liệt kê và giải thích trên trang chủ cũng khá đầy đủ

Sau đây chúng ta sẽ điểm qua những câu lệnh nào hay sử dụng nhất.

4.1 Thiết lập thông tin cơ bản

  • FROM

    • Ví dụ:

      FROM centos:7
      FROM ubuntu:16.04
      FROM ubuntu:22.04
      ...
      FROM ubuntu:latest
      
    • Câu lệnh này luôn nằm đầu tiên, nó giúp chúng ta chỉ định image ta đang muốn tạo khởi nguồn từ đâu.

    • Hiểu nôm na là bắt nguồn từ ubuntu, hay centos ... cùng phiên bản của nó (latest có nghĩa là phiên bản mới nhất) sau đó cài thêm những gì lên.

    • Có thể bạn đã biết, Docker hub - nơi lưu trữ và chia sẻ các image sẽ chứa những image gốc này.

    • Khi Docker đọc tới câu lệnh này, nó sẽ tự động tìm xem image ubuntu:16.04 này đã tồn tại trong host OS chưa, nếu chưa thì Docker sẽ tự động pull image này về. Trong đó ubuntu là tên của image, 16:04 là tag, latest nghĩa là tag mới nhất.

  • WORKDIR

    • Ví dụ:

      WORKDIR /app
      WORKDIR /path/to/workdir
      
    • Thay đổi thư mục làm việc

4.2 Cài thêm ứng dụng

Bây giờ, chúng ta sẽ cài thêm các ứng dụng, thiết lập môi trường cần thiết trên ubuntu:16.04 này

Bạn có thể cài nginx, php, python, ruby, java ... phụ thuộc vào nhu cầu của bạn, sử dụng:

  • RUN : Để thực thi một câu lệnh nào đó trong quá trình build images.

  • CMD : Để thực thi một câu lệnh trong quá trình bật container.

    Mỗi Dockerfile chỉ có một câu lệnh CMD, nếu như có nhiều hơn một câu lệnh CMD thì chỉ có câu lệnh CMD cuối cùng được sử dụng.

    Một câu hỏi đặt ra là nếu tôi muốn khởi động nhiều ứng dụng khi start container thì sao, lúc đó hay nghĩ tới ENTRYPOINT

  • ENTRYPOINT: Để thực thi một số câu lệnh trong quá trình start container, những câu lệnh này sẽ được viết trong file .sh.

Ví dụ:

# Update ubuntu
RUN apt-get update

# Install nginx
RUN apt-get install -y nginx

# Install mysql server
RUN echo "mysql-server mysql-server/root_password password root" | debconf-set-selections \
    && echo "mysql-server mysql-server/root_password_again password root" | debconf-set-selections \
    && apt-get install -y mysql-server

Trong khi cài nginx, sẽ có câu hỏi xuất hiện và bạn cần trả lời yes/no, khi đó tùy chọn -y trong RUN apt-get install -y nginx sẽ thể hiện cho sự lựa chọn yes của bạn.

4.3 Cấu hình

  • EXPOSE: Container sẽ lắng nghe trên các cổng mạng được chỉ định khi chạy

  • ADD : Copy file, thư mục, remote file thêm chúng vào filesystem của image.

  • COPY : Copy file, thư mục từ host machine vào image. Có thể sử dụng url cho tập tin cần copy.

  • WORKDIR : Định nghĩa directory cho CMD

  • VOLUME : Mount thư mục từ máy host vào container.

Tạo file .sh

Như ở phần entrypoint đã nói, cho dù chỉ cần một câu lệnh mình vẫn dùng ENTRYPOINT, để sau này dễ dàng tùy biến, phát triển.

Tạo file start.sh như sau

#!/bin/bash
service nginx start
exec $@

Ta có ví dụ ở phần này như sau:

ADD start.sh /venv

WORKDIR /venv

RUN chmod a+x /venv/*

ENTRYPOINT ["/venv/start.sh"]

EXPOSE 80

Tổng hợp lại, ta có một ví dụ cho Dockerfile như sau :

FROM ubuntu:16.04

MAINTAINER HoanKi<hoanki2212@gmail.com>

RUN DEBIAN_FRONTEND=noninteractive

RUN apt-get update

RUN apt-get install -y nginx

RUN echo "mysql-server mysql-server/root_password password root" | debconf-set-selections \
    && echo "mysql-server mysql-server/root_password_again password root" | debconf-set-selections \
    && apt-get install -y mysql-server

WORKDIR /venv

COPY start.sh /venv

RUN chmod a+x /venv/*

ENTRYPOINT ["/venv/start.sh"]

EXPOSE 80
  • Tạo file hello.html trong thư mục webroot:
<h1>Hello word</h1>

5. Cách sử dụng Dockerfile

5.1 Build docker image từ Dockerfile

Ta sử dụng câu lệnh sau:

sudo docker build -t <image_name> .

Ví dụ:

sudo docker build -t ubuntu-nginx . 

Bạn có thể dùng lệnh

docker images

để xem thành quả nhé !

5.2 Tạo container từ image.

  • Gõ lệnh theo syntax:

sudo docker run -v <forder_in_computer>:<forder_in_container> -p <port_in_computer>:<port_in_container> -it <image_name> /bin/bash

Trong đó:

  • -v : Thể hiện việc mount volume, dữ liệu từ thư mục từ máy thật có thể được truy cập từ thư mục của máy ảo.

  • -p: Cổng mạng từ máy thật để dẫn tới cổng mạng của máy ảo đang chạy.

  • -t: Chạy container và mở terminal bằng /bin/bash

  • Ví dụ vào localhost mặc định của nginx:

sudo docker run -p 9000:80 -it ubuntu-nginx /bin/bash

Kiểm tra log trên Terminal:

Trên trình duyệt:

  • Ví dụ vào thư mục dự án ở máy thật:
sudo docker run -v  /media/hoanki/PROJECT4/GitRepo/docker_tutorial/webroot:/var/www/html -p 9000:80 -it ubuntu-nginx /bin/bash

Thay thế /media/hoanki/PROJECT4/GitRepo/docker_tutorial/webroot cho đúng với trên máy bạn nhé !

Kết quả:

6. Cách chia sẻ Dockerfile

Docker-hub: Nơi lưu trữ và chia sẻ các image của Docker, nhưng không chỉ có vậy.

Nãy giờ bạn và tôi đang build image hoàn toàn dưới local, nhưng Docker Hub còn hỗ trợ chúng ta làm việc này trên server nữa.

  • Mình tạo mới repo docker-basic trên Github, như này:

  • Sau đó mình tạo mới một repo trên Dockerhub.

Vào Create chọn Create Automated Build, chọn Github rồi trỏ tới docker-basic bạn vừa tạo ở GitHub.

Và ta có docker_basic, trông như sau:

  • Dockerhub sẽ hỗ trợ bạn build docker image online, sau đó bạn có thể pull nó về để sử dụng.

  • Vào tab Build Settings,

  • Từ giờ trở đi, mỗi khi bạn push code lên branch nào trên github branch đó bạn đã setting trên DockerHub thì images sẽ tự động được build.

Việc build này sẽ tự động thực hiên trên server Docker Hub nhé, ví dụ mình push code lên branch init_dockerfile thì Dockerhub tự động build image, kết quả có ở trong tab Build Detail.

Mình tạo pull request, sau khi mình merge nó thì DockerHub cũng sẽ build image tiếp trên branch master.

  • Thử đi nhé, đôi khi buid ở local thì pass mà build trên server thì lỗi, cảm giác fix mãi nó mới hiện dòng chữ "Success" nó mới awesome làm sao.

###############################################

😄 😄 😄 Thank for your attention 😄 😄 😄

😄 😄 😄 Mình đã viết xong Docker: Chưa biết gì đến biết dùng (Phần 3), mời các bạn đọc tiếp. 😄 😄 😄


All rights reserved

Bình luận

Đang tải thêm bình luận...
Avatar
+300
Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí