Tạo docker image Caddy Alpine

cuong@techmaster.vn

https://github.com/TechMaster/CaddyAlpine

Muốn thử ngay

git clone https://github.com/TechMaster/CaddyAlpine.git
cd CaddyAlpine

docker build sau đó khởi động caddy phục vụ web site tối giản ở http://locahost

./rebuild
./website

tạo container phục vụ web site tĩnh lưu ở host

./hostmd

tạo container phục vụ web site gồm các file Markdown

Caddy

  • Viết bằng Go
  • Rất dễ cấu hình, Caddyfile
  • Host trang cá nhân, thử nghiệm
  • Tốc độ  80% nginx, tiếp tục cải thiện
  • Hỗ trợ HTTP/2
  • Hỗ trợ multicore (nhờ Go)
  • Có nhiều plugins, dễ dùng

Nginx

  • Viết bằng C
  • Cấu hình nhiều file *.conf
  • Thích hợp môi trường sản xuất
  • Vô địch tốc độ, bảo mật
  • Hỗ trợ HTTP/2 một phần
  • Có nhiều plugins, cấu hình khó

https://ferdinand-muetsch.de/caddy-a-modern-web-server-vs-nginx.html

Tái sử dụng -> cải tiến

  1. Trước khi viết Dockerfile hãy tìm trên Docker Hub xem có image phù hợp yêu cầu chưa. Có rồi đừng mất công viết lại
  2. Chưa vừa ý hãy học tập từ Dockerfile sẵn có, rồi cải tiến
docker run --name yobacaddy -d -p 80:2015 yobasystems/alpine-caddy

Tạo container dùng alpine-caddy của Yoba

web server chạy OK !

Cải tiến những điểm gì ?

  • Giảm kích thước Docker image
  • Giảm thời gian build image: docker build
  • Giảm thời gian tạo mới container: docker run
  • Tăng khả năng tái sử dụng image. Dùng để tạo ra các image khác nhau
  • Tăng cường bảo mật
FROM yobasystems/alpine:amd64
LABEL maintainer "Dominic Taylor <dominic@yobasystems.co.uk>" architecture="AMD64/x86_64"

ARG plugins=http.git

RUN apk add --update openssh-client git tar curl

RUN curl --silent --show-error --fail --location \
--header "Accept: application/tar+gzip, application/x-gzip, application/octet-stream" -o - \
      "https://caddyserver.com/download/linux/amd64?plugins=${plugins}" \
    | tar --no-same-owner -C /usr/bin/ -xz caddy && \
    chmod 0755 /usr/bin/caddy && \
    addgroup -S caddy && \
    adduser -D -S -H -s /sbin/nologin -G caddy caddy && \
    /usr/bin/caddy -version

EXPOSE 80 443 2015
VOLUME /srv
WORKDIR /srv

ADD files/Caddyfile /etc/Caddyfile
ADD files/index.html /srv/index.html

RUN chown -R caddy:caddy /srv

USER caddy

ENTRYPOINT ["/usr/bin/caddy"]
CMD ["--conf", "/etc/Caddyfile"]

Đây là Dockerfile tại

https://github.com/yobasystems/alpine-caddy

Những điểm chưa hài lòng với Yobasystems/alpine-caddy

  1. Cài thêm nhiều gói không cần thiết -> image size tăng

  2. Lệnh cài đặt phức tạp không tự nhận biết kiến trúc CPU container đang chạy

     

docker exec -it yobacaddy /bin/sh

/srv $ whoami
caddy
/srv $ touch about.html
touch: about.html: Permission denied
/srv $ ls -all .
total 12
drwxr-xr-x    2 root     root          4096 Dec 28 04:14 .
drwxr-xr-x    1 root     root          4096 Dec 28 04:14 ..
-rw-r--r--    1 root     root           460 Dec 24 06:17 index.html
RUN chown -R caddy:caddy /srv

Yoba Dockerfile đổi chủ (owner) cho thư mục /srv từ root sang caddy

Khi vào container, user caddy  vẫn không có quyền với thư mục /srv

FROM alpine:latest
MAINTAINER "Trinh Minh Cuong <cuong@techmaster.vn>"

RUN apk add --no-cache curl bash libcap \
&& curl https://getcaddy.com | bash -s personal \
&& chmod 0755 /usr/local/bin/caddy \
&& addgroup -S caddy \
&& adduser -D -S -H -s /sbin/nologin -G caddy caddy \
&& setcap CAP_NET_BIND_SERVICE=+eip /usr/local/bin/caddy \
&& apk del curl bash libcap

EXPOSE 80 443 2015
#VOLUME /srv Phải bỏ lệnh này vì nó vô hiệu hoá RUN chown -R caddy:caddy /srv
WORKDIR /srv

COPY files/Caddyfile /etc/Caddyfile
COPY files/index.html /srv/index.html

RUN chown -R caddy:caddy /srv

USER caddy

ENTRYPOINT ["/usr/local/bin/caddy"]
CMD ["--conf", "/etc/Caddyfile"]

Dockerfile cải tiến

  1. Cài curl, bash, libcap

  2. Dùng curl tải file bash script cài đặt Caddy

  3. Dọn dẹp sau cài đặt

  4. Tạo group và user caddy
  5. Cho phép file binary /usr/local/bin/caddy được chạy bởi non-root user
  6. Biến caddy thành chủ thư mục /srv
  7. Mở cổng 80, 443, 2015
  8. Đặt thư mục /srv là thư mục mặc định khi container chạy
  9. Chọn user caddy là user chạy docker container
  10. Copy index.html vào /srv, file cấu hình Caddyfile vào /etc
  11. Khởi động

Cài đặt Caddy

  1. curl: tải file cài đặt Caddy

     
  2. bash: thực thi bashscript cài đặt Caddy
curl https://getcaddy.com | bash -s personal
apk --no-cache add curl bash libcap

root hay non-root bên trong container

Mặc định Alpine container khởi động bằng user root

Quyền lực vô biên nhưng có nhiều rủi ro bảo mật:
root trong container  cài - xoá phần mềm, kết nối ra ngoài

chmod 0755 /usr/local/bin/caddy
addgroup -S caddy
adduser -D -S -H -s /sbin/nologin -G caddy caddy

Cho phép mọi user khác đọc, thực thi

Tạo group caddy

Tạo caddy rồi cho vào group caddy

Giới hạn quyền non-root user đúng tài nguyên và thư mục cần thiết

Linux mặc định chỉ cho root chạy ứng dụng lắng nghe ở cổng thấp

Để ứng dụng chạy bởi non-root gắn được vào cổng thấp như 21, 23, 25, 80

setcap CAP_NET_BIND_SERVICE=+eip /usr/local/bin/caddy

setcap nằm trong gói libcap

VOLUME vô hiệu hoá lệnh phân quyền thư mục /srv cho user caddy

VOLUME /srv
RUN chown -R caddy:caddy /srv

Học được gì từ Caddy Alpine

  1. WORKDIR: thư mục làm việc mặc định
  2. EXPOSE : mở cổng từ container
  3. USER: chọn user khác root
  4. Tạo user, group trong Alpine, phân quyền thư mục
  5. Cho phép non-root user chạy ứng dụng ở cổng 80

Để tăng tốc build docker build

  1. Xếp những lệnh tạo layer ít thay đổi lên trên cùng
  2. Đừng cài gói phần mềm không cần thiết
  3. Chuyển những lệnh cần tinh chỉnh nhiều xuống cuối Dockerfile
  4. Không dùng quá lần apk add --no-cache

Viết script để tự động hoá việc build image và kiểm thử

Tôi viết script cho Fish Shell thực thi. Nếu bạn chỉ có Bash thì hãy đổi lại dòng đầu tiên thành

#!/bin/bash

#!/usr/local/bin/fish
docker stop caddy
docker rm caddy
docker build -t caddyalpine .
docker run --name caddy -p 80:80 -d caddyalpine
curl http://localhost

Build docker image sau đó dùng curl để kiểm tra web site có hoạt động không?

#!/usr/local/bin/fish
docker stop caddy
docker rm caddy
docker run --name caddy -v $PWD/DockerFarm:/srv/ -p 80:80 -d caddyalpine
curl http://localhost

Host web site tĩnh ở thư mục DockerFarm
chạy curl để kiểm tra

$PWD trả về đường dẫn thư mục hiện thời

#!/usr/local/bin/fish
docker stop caddy
docker rm caddy
docker run --name caddy -v $PWD/md/:/srv -p 80:80 -d caddyalpine --conf /srv/Caddyfile
curl http://localhost

Host web site chứa file Markdown

Để host được markdown, phải dùng Caddyfile lưu ở thư mục book map vào container là /srv

Caddyfile

:80
browse
markdown /
log stdout
errors stdout
:80
markdown / {
    template blog templates/blog.html
    template index templates/index.html
}
log stdout
errors stdout

phục vụ thư mục nếu không có file index.html

render file Markdown ra HTML

Made with Slides.com