Thursday, November 21, 2024

[Docker] Phần 16 – Khởi chạy dịch vụ tự động khi start Container

-

Trong thế giới phát triển và triển khai ứng dụng, việc sử dụng Docker để đóng gói và chạy các ứng dụng trong các container đã trở thành một phần quan trọng của quy trình phát triển. Tuy nhiên, một trong những thách thức mà các nhà phát triển và quản trị hệ thống thường gặp phải là cách để dịch vụ trong container tự động khởi chạy khi container được bật.

Trong bài viết này, mình sẽ hướng dẫn bạn về ba cách thường được sử dụng để thực hiện điều này:

  • Tạo một script khởi động.
  • Sử dụng Docker Compose.
  • Sử dụng entrypoint script.

Mình sẽ cung cấp hướng dẫn chi tiết và ví dụ cụ thể cho mỗi phương pháp, giúp bạn hiểu cách tự động khởi chạy dịch vụ trong container Docker một cách dễ dàng và hiệu quả.

Để dịch vụ của bạn tự động khởi chạy khi container được bật, bạn có thể sử dụng các phương pháp sau:

Tạo một script khởi động: Tạo một script khởi động (ví dụ: startup.sh) trong container của bạn. Script này sẽ chứa các lệnh cần thiết để khởi động dịch vụ của bạn. Đảm bảo script có quyền thực thi (chmod +x startup.sh). Sau đó, chỉnh sửa tệp Dockerfile của bạn và thêm dòng sau vào cuối tệp:

CMD /path/to/startup.sh

Thay /path/to/startup.sh bằng đường dẫn đúng đến script khởi động của bạn. Khi container được bật, Docker sẽ tự động thực thi script này và khởi động dịch vụ.

Sử dụng Docker Compose: Nếu bạn đang sử dụng Docker Compose để quản lý container, bạn có thể thêm một mục command vào tệp docker-compose.yml. Ví dụ:

services:
  myservice:
    build:
      context: .
      dockerfile: Dockerfile
    command: /path/to/startup.sh

Thay /path/to/startup.sh bằng đường dẫn đúng đến script khởi động của bạn. Khi bạn chạy docker-compose up, Docker Compose sẽ tự động thực thi script này và khởi động dịch vụ.

Sử dụng entrypoint script: Nếu bạn không muốn sử dụng CMD trong Dockerfile, bạn có thể tạo một entrypoint script để thực thi khi container khởi động. Entry point script có thể kiểm tra và khởi động dịch vụ của bạn. Đảm bảo script có quyền thực thi (chmod +x entrypoint.sh). Sau đó, chỉnh sửa Dockerfile của bạn và thêm dòng sau:

ENTRYPOINT ["/path/to/entrypoint.sh"]

Thay /path/to/entrypoint.sh bằng đường dẫn đúng đến entrypoint script của bạn. Khi container được bật, Docker sẽ thực thi entrypoint script và khởi động dịch vụ.

Nếu entrypoint script của bạn chỉ khởi chạy dịch vụ và kết thúc sau khi dịch vụ được khởi động, container sẽ dừng lại sau khi công việc hoàn thành. Để giữ cho container hoạt động sau khi dịch vụ được khởi chạy, bạn có thể sử dụng một giải pháp đơn giản như tail -f /dev/null trong script entrypoint.

Cụ thể, thay vì kết thúc entrypoint script sau khi khởi chạy dịch vụ, bạn thêm lệnh tail -f /dev/null để giữ cho quá trình của script tiếp tục chạy và container không dừng lại. Ví dụ:

#!/bin/bash

# Start your service here
/path/to/your_service &

# Keep the script running
tail -f /dev/null

Bằng cách thêm tail -f /dev/null vào cuối script, container sẽ tiếp tục chạy và không bị dừng sau khi dịch vụ khởi động xong. Lưu ý rằng nếu entrypoint script của bạn có các công việc khác cần được thực hiện sau khi khởi động dịch vụ, bạn vẫn có thể thực hiện chúng trước lệnh tail -f /dev/null.

Sau khi bạn đã sửa đổi script entrypoint, hãy build lại image và chạy container từ image mới để kiểm tra xem container có tiếp tục chạy sau khi dịch vụ được khởi động hay không.

Lưu ý rằng các phương pháp trên tùy thuộc vào việc bạn sử dụng Dockerfile hoặc Docker Compose để xây dựng và chạy container. Chọn phương pháp phù hợp với công cụ mà bạn đang sử dụng để quản lý container.

Ví dụ tạo một Dockerfile với nội dung sau:

cat > ./Dockerfile << OEF
FROM hoanghd164/gitlab:1.0.1
WORKDIR /home

# Copy entrypoint script to the container
COPY entrypoint.sh /usr/local/bin/entrypoint.sh

# Set execute permissions for the entrypoint script
RUN chmod +x /usr/local/bin/entrypoint.sh

# Install Jenkins
RUN curl -fsSL https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key | tee /usr/share/keyrings/jenkins-keyring.asc > /dev/null
RUN echo deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] https://pkg.jenkins.io/debian-stable binary/ | tee /etc/apt/sources.list.d/jenkins.list > /dev/null
RUN apt-get update
RUN apt-get install jenkins -y
RUN apt install openjdk-11-jre -y
RUN sed -i 's/HTTP_PORT=8080/HTTP_PORT=8000/' /etc/default/jenkins
RUN sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
RUN sed -i 's/#PasswordAuthentication yes/PasswordAuthentication yes/' /etc/ssh/sshd_config
RUN sed -i 's/#PasswordAuthentication yes/PasswordAuthentication yes/' /etc/ssh/sshd_config
RUN sed -i 's/#Port 22/Port 22/' /etc/ssh/sshd_config

# Define the entrypoint command
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
OEF

Trong đoạn Dockerfile trên, chúng ta đang tạo một Docker image mới từ base image hoanghd164/gitlab:1.0.1. Đầu tiên, chúng ta đặt thư mục làm việc là /home.

Tiếp theo, chúng ta sao chép tệp tin entrypoint.sh vào container tại đường dẫn /usr/local/bin/entrypoint.sh. Sau đó, chúng ta đặt quyền thực thi cho tệp tin entrypoint.sh bằng câu lệnh RUN chmod +x /usr/local/bin/entrypoint.sh.

Tiếp theo, chúng ta tiến hành cài đặt Jenkins bằng cách thêm keyring và sources.list từ Jenkins repository. Sau đó, chúng ta cập nhật gói và cài đặt Jenkins bằng câu lệnh apt-get install jenkins -y. Đồng thời, chúng ta cũng cài đặt OpenJDK 11 Runtime Environment bằng câu lệnh apt install openjdk-11-jre -y.

Cuối cùng, chúng ta định nghĩa lệnh entrypoint cho container bằng cách sử dụng ENTRYPOINT với đường dẫn /usr/local/bin/entrypoint.sh.

Sau khi tạo Dockerfile, chúng ta tạo tệp tin entrypoint.sh với nội dung tương tự như trước đó.

cat > ./entrypoint.sh << 'OEF'
#!/bin/bash
/etc/init.d/ssh start
sleep 1
/opt/gitlab/embedded/bin/runsvdir-start & gitlab-ctl start
sleep 1
/etc/init.d/jenkins start
sleep 1
tail -f /dev/null
OEF

Cuối cùng, chúng ta sử dụng lệnh docker build để tạo image mới với tag hoanghd164/gitlab:1.0.2 từ Dockerfile và các tệp tin trong thư mục hiện tại. Tùy chọn --force-rm được sử dụng để gỡ bỏ các container tạm thời sau khi xây dựng xong.

docker build -t hoanghd164/gitlab:1.0.2 --force-rm -f Dockerfile .

Bạn có kết quả.

$ docker image ls | grep hoanghd164/gitlab
hoanghd164/gitlab          1.0.2     30330e2f271b   6 minutes ago    4.53GB
hoanghd164/gitlab          1.0.1     1fbf0382df39   11 hours ago     4.09GB

Lệnh docker build sẽ đọc Dockerfile và tệp tin liên quan, sau đó tạo một image mới dựa trên các chỉ thị và lệnh được định nghĩa trong Dockerfile.

Giờ bạn có thể run image này để sử dụng được rồi.

version: "3"
services:
  gitlab:
    container_name: gitlab
    image: hoanghd164/gitlab:1.0.2
    privileged: true
    stdin_open: true
    tty: true
    restart: always
    ports:
      - "80:80"
      - "8000:8000"
      - "22:22"
    volumes:
      - /Users/hoanghd/Dropbox:/home
    networks:
      - network_cicd
networks:
  network_cicd:

Sử dụng lệnh docker-compose up -d để chạy container này và bạn có kết quả như dưới.

$ docker-compose ps
NAME                IMAGE                     COMMAND                  SERVICE             CREATED             STATUS              PORTS
gitlab              hoanghd164/gitlab:1.0.2   "/usr/local/bin/entr…"   gitlab              7 minutes ago       Up 7 minutes        0.0.0.0:80->80/tcp, 0.0.0.0:8080->8080/tcp

Bạn có kết quả logs xuất ra khi chạy /usr/local/bin/entrypoint.sh.

$ docker logs gitlab
 * Starting Jenkins Automation Server jenkins                                   Correct java version found
Setting up max open files limit to 8192
                                                                         [ OK ]
ok: run: alertmanager: (pid 138) 1s
ok: run: gitaly: (pid 113) 1s
ok: run: gitlab-exporter: (pid 124) 1s
ok: run: gitlab-kas: (pid 119) 1s
ok: run: gitlab-workhorse: (pid 114) 1s
ok: run: logrotate: (pid 141) 1s
ok: run: nginx: (pid 128) 1s
ok: run: node-exporter: (pid 112) 1s
ok: run: postgres-exporter: (pid 118) 1s
ok: run: postgresql: (pid 120) 1s
ok: run: prometheus: (pid 132) 1s
ok: run: puma: (pid 131) 1s
ok: run: redis: (pid 122) 1s
ok: run: redis-exporter: (pid 127) 1s
ok: run: sidekiq: (pid 111) 1s

Trong bài viết này, chúng ta đã tìm hiểu cách tự động khởi chạy dịch vụ trong một container Docker khi container được bật. Điều này là quan trọng trong việc quản lý ứng dụng Docker, đảm bảo rằng các dịch vụ và ứng dụng của bạn sẽ được khởi động một cách tự động và đáng tin cậy.

Chúng ta đã xem xét ba phương pháp cụ thể để thực hiện điều này: tạo một script khởi động, sử dụng Docker Compose và sử dụng entrypoint script. Mỗi phương pháp có ưu điểm và sử dụng trong các tình huống khác nhau.

Với kiến thức này, bạn có thể tùy chọn phương pháp phù hợp với dự án của bạn và triển khai container Docker một cách tự động và hiệu quả. Điều này giúp tối ưu hóa quy trình phát triển và triển khai của bạn và đảm bảo rằng các dịch vụ của bạn luôn sẵn sàng hoạt động.

LEAVE A REPLY

Please enter your comment!
Please enter your name here

4,956FansLike
256FollowersFollow
223SubscribersSubscribe
spot_img

Related Stories