Chuyển đến nội dung chính

Proxy Docker: Hướng dẫn đầy đủ để container hoạt động phía sau tường lửa doanh nghiệp

Tìm hiểu cách thiết lập cấu hình proxy ở mọi lớp để thao tác Docker của bạn hoạt động ổn định phía sau tường lửa doanh nghiệp.
· 15 phút đọc

Khám phá cùng AI

Hầu hết các mạng doanh nghiệp sử dụng máy chủ proxy để giám sát và lọc lưu lượng internet. Điều này tạo ra rào cản khi Docker cố tải image từ các registry. Bạn sẽ gặp timeout kết nối, lỗi xác thực và các bản build thất bại dù vẫn chạy được ở mạng gia đình. Những sự cố liên quan đến proxy này có thể làm gián đoạn đội ngũ phát triển khi họ không truy cập được các base image cần thiết.

Cấu hình proxy cho Docker giải quyết các vấn đề kết nối này, đồng thời cải thiện hiệu năng nhờ cơ chế cache và đáp ứng yêu cầu bảo mật của doanh nghiệp. Sau khi cấu hình, container của bạn sẽ tải image bất chấp các hạn chế mạng.

Trong hướng dẫn này, tôi sẽ đưa bạn qua các bước thiết lập proxy cho Docker daemon, cấu hình biến môi trường cho container và xử lý cấu hình proxy trong Docker Compose.

Mới dùng Docker và cảm thấy choáng ngợp với các khái niệm mạng? Bắt đầu với các nền tảng Docker và xây dựng sự tự tin từng bước.

Tìm hiểu kiến trúc Proxy của Docker

Các phần khác nhau trong hệ sinh thái Docker cần cấu hình proxy ở các lớp khác nhau.

Proxy đóng vai trò trung gian giữa các thành phần Docker và mạng bên ngoài. Khi Docker cần tải image, container cần truy cập internet, hoặc quá trình build cần tài nguyên bên ngoài, máy chủ proxy sẽ kiểm soát và giám sát các kết nối này. Chúng nằm giữa ứng dụng đóng gói của bạn và thế giới bên ngoài, lọc cả request và response.

Tổ chức sử dụng proxy với Docker vì hiệu năng, bảo mật và tuân thủ.

Hiệu năng đến từ việc cache các tài nguyên được truy cập thường xuyên như base image, giảm thời gian tải cho cả team. Lợi ích bảo mật gồm lọc lưu lượng, quét malware và chặn truy cập đến các trang không được phép. Yêu cầu tuân thủ đòi hỏi toàn bộ lưu lượng mạng phải đi qua các kênh được giám sát với kiểm soát truy cập và dấu vết kiểm toán đầy đủ.

Cấu hình proxy cho Docker diễn ra ở bốn lớp:

  • Proxy phía client: ảnh hưởng đến lệnh Docker CLI như docker pull và docker push

  • Proxy cho daemon: kiểm soát cách Docker daemon truy cập registry bên ngoài  

  • Proxy khi chạy container: thiết lập biến proxy cho ứng dụng bên trong container

  • Proxy lúc build: xử lý cài đặt proxy trong các thao tác docker build khi Dockerfile cần truy cập internet

Mỗi lớp có vai trò riêng và cần cách cấu hình riêng.

Hiểu về mạng trong Docker bắt đầu từ việc nắm cách container giao tiếp với nhau. 

Cấu hình Docker để dùng Proxy

Để Docker hoạt động với proxy doanh nghiệp, bạn cần thiết lập cả Docker daemon và client.

Vì sao? Vì chúng xử lý các loại yêu cầu mạng khác nhau. 

Daemon quản lý việc kéo, đẩy image và xác thực với registry, trong khi client xử lý thao tác CLI và các lời gọi API. Thiếu một trong hai cấu hình sẽ để lại khoảng trống khiến thao tác Docker thất bại với lỗi kết nối.

Cách cấu hình Docker daemon

Docker daemon đọc cài đặt proxy từ /etc/docker/daemon.json. Tạo file này nếu chưa tồn tại:

{
  "proxies": {
    "default": {
      "httpProxy": "http://proxy.company.com:8080",
      "httpsProxy": "http://proxy.company.com:8080",
      "noProxy": "localhost,127.0.0.1,.company.com"
    }
  }
}

Trường noProxy liệt kê các địa chỉ nên bỏ qua proxy. Thêm domain registry nội bộ và địa chỉ localhost của bạn vào đây.

Thiết lập override cho dịch vụ systemd

Trên các hệ Linux dùng systemd, bạn cũng cần cấu hình chính dịch vụ Docker để dùng proxy. Tạo thư mục override và file cấu hình:

sudo mkdir -p /etc/systemd/system/docker.service.d
sudo nano /etc/systemd/system/docker.service.d/http-proxy.conf

Sau đó, thêm các biến môi trường này vào file http-proxy.conf:

[Service]
Environment="HTTP_PROXY=http://proxy.company.com:8080"
Environment="HTTPS_PROXY=http://proxy.company.com:8080"
Environment="NO_PROXY=localhost,127.0.0.1,.company.com"

Điều này đảm bảo chính tiến trình Docker daemon có thể truy cập dịch vụ bên ngoài qua proxy của bạn.

Docker sẽ không nhận thay đổi proxy cho đến khi bạn khởi động lại daemon. Chạy các lệnh này để nạp lại systemd và khởi động Docker:

sudo systemctl daemon-reload
sudo systemctl restart docker

Lệnh reload daemon yêu cầu systemd đọc cấu hình dịch vụ mới, còn khởi động lại Docker sẽ áp dụng thay đổi trong daemon.json.

Lưu ý theo nền tảng

Docker Desktop xử lý cấu hình proxy khác với bản cài trên máy chủ. Trên Windows và macOS, dùng giao diện Docker Desktop để đặt proxy trong mục Resources - Proxies. Các cài đặt này sẽ tự động cấu hình cả daemon và client.

Host Linux dùng Docker Engine cần làm thủ công như mô tả ở trên. Một số bản phân phối đóng gói Docker khác nhau, vì vậy hãy kiểm tra hệ thống của bạn dùng dockerd trực tiếp hay qua một trình quản lý dịch vụ khác.

Xác minh cấu hình

Kiểm tra Docker có thể truy cập registry bên ngoài với lệnh pull đơn giản:

docker pull hello-world

Bạn cũng có thể xem cấu hình hiệu lực của daemon:

docker system info | grep -i proxy

Lệnh này hiển thị Docker có phát hiện và áp dụng cài đặt proxy hay không.

Nếu việc pull vẫn thất bại, kiểm tra log của máy chủ proxy để xác nhận Docker định tuyến request đúng cách.

Gặp rắc rối với mạng? Mở cổng Docker đúng cách để tránh đau đầu về kết nối.

Thiết lập biến môi trường Proxy

Các lệnh Docker CLI cần cấu hình proxy riêng, tách biệt với cài đặt của daemon. Biến môi trường giúp bạn linh hoạt kiểm soát cách Docker client kết nối qua proxy doanh nghiệp.

Proxy phía client điều khiển các thao tác CLI như docker pull, docker push và docker login. Khi bạn chạy các lệnh này, Docker client sẽ gửi HTTP request đến registry và cần biết máy chủ proxy nào để dùng. Thiếu cài đặt proxy cho client, các thao tác này sẽ thất bại ngay cả khi daemon đã cấu hình đúng.

Phương pháp cấu hình JSON

Cách gọn gàng nhất là dùng file cấu hình của Docker tại ~/.docker/config.json:

{
  "proxies": {
    "default": {
      "httpProxy": "http://proxy.company.com:8080",
      "httpsProxy": "http://proxy.company.com:8080",
      "noProxy": "localhost,127.0.0.1,.company.com"
    }
  }
}

Cách này giữ cài đặt proxy nằm trong cấu hình của Docker và không ảnh hưởng đến ứng dụng khác trên hệ thống.

Phương án dùng biến môi trường

Bạn cũng có thể đặt các biến môi trường proxy tiêu chuẩn mà Docker sẽ tự động phát hiện bằng các lệnh sau:

export HTTP_PROXY=http://proxy.company.com:8080
export HTTPS_PROXY=http://proxy.company.com:8080
export NO_PROXY=localhost,127.0.0.1,.company.com

Các biến này hoạt động với bất kỳ ứng dụng nào tuân thủ tiêu chuẩn proxy - không chỉ Docker.

Cấu hình toàn hệ thống và theo người dùng

Đối với cấu hình toàn hệ thống, thêm các biến môi trường vào /etc/environment hoặc tạo script trong /etc/profile.d/:

# /etc/profile.d/proxy.sh
export HTTP_PROXY=http://proxy.company.com:8080
export HTTPS_PROXY=http://proxy.company.com:8080
export NO_PROXY=localhost,127.0.0.1,.company.com

Đối với cấu hình theo người dùng, thêm chúng vào profile shell của bạn (~/.bashrc, ~/.zshrc) hoặc dùng cách cấu hình JSON. Cài đặt theo người dùng cho phép nhà phát triển linh hoạt dùng proxy khác hoặc bỏ qua hoàn toàn khi thử nghiệm.

Lưu ý bảo mật

Bạn không bao giờ nên hard-code tên người dùng và mật khẩu trong file cấu hình hoặc biến môi trường. 

Thông tin xác thực proxy ở dạng văn bản thuần tạo rủi ro bảo mật, đặc biệt trong môi trường dùng chung hoặc hệ thống quản lý phiên bản.

Thay vào đó, hãy dùng các cách sau:

  • Cấu hình máy chủ proxy xác thực theo IP khi có thể
  • Dùng trình trợ giúp lưu trữ thông tin xác thực hoặc hệ thống lưu trữ an toàn
  • Thiết lập tài khoản dịch vụ với quyền tối thiểu cho thao tác Docker

Nếu buộc phải đưa thông tin xác thực, dùng định dạng http://username:[email protected]:8080, nhưng lưu trong file được bảo vệ với quyền hạn chế.

Cấu hình proxy lúc build

Quá trình build Docker cần truyền cài đặt proxy một cách tường minh qua build argument:

docker build \
  --build-arg HTTP_PROXY=http://proxy.company.com:8080 \
  --build-arg HTTPS_PROXY=http://proxy.company.com:8080 \
  --build-arg NO_PROXY=localhost,127.0.0.1 \
  -t myapp .

Build argument sẽ trở thành biến môi trường bên trong ngữ cảnh build.

Điều này cho phép các lệnh RUN tải gói và phụ thuộc qua proxy của bạn. Không có các argument này, quá trình build sẽ thất bại khi Dockerfile cố cài phần mềm hoặc lấy tài nguyên từ internet.

Cài đặt proxy lúc build sẽ không tồn tại trong image cuối cùng trừ khi bạn đặt tường minh bằng lệnh ENV trong Dockerfile.

Biến môi trường cho bạn sự linh hoạt để xử lý cài đặt proxy ở cấp độ phù hợp với quy trình làm việc.

Bạn thấy build argument khó hiểu? Nắm vững build args của Docker với các ví dụ thực tế hoạt động được.

Tiêm Proxy vào Container và lúc Build

Cấu hình client của Docker mới chỉ là nửa chặng đường - container và quá trình build của bạn cần cài đặt proxy riêng. Ở phần này, tôi sẽ chỉ bạn cách tiêm cấu hình proxy lúc runtime và build time.

Biến môi trường lúc runtime

Container không kế thừa cài đặt proxy của host.

Bạn cần truyền biến proxy một cách tường minh khi khởi chạy container. Docker cung cấp nhiều cách làm, tùy bạn muốn cấu hình cho tất cả container hay chỉ một số cụ thể.

Cấu hình JSON là cách gọn gàng nhất để tạo sự nhất quán về cài đặt proxy - như đã bàn bên trên. Tóm lại, thêm phần này vào ~/.docker/config.json của bạn:

{
  "proxies": {
    "default": {
      "httpProxy": "http://proxy.company.com:8080",
      "httpsProxy": "http://proxy.company.com:8080",
      "noProxy": "localhost,127.0.0.1,.company.com"
    }
  }
}

Docker sẽ tự động tiêm các biến này vào mọi container bạn khởi chạy. Không cần thêm cờ gì nữa.

Cờ CLI cho bạn kiểm soát chi tiết theo từng container:

docker run \
  --env HTTP_PROXY=http://proxy.company.com:8080 \
  --env HTTPS_PROXY=http://proxy.company.com:8080 \
  --env NO_PROXY=localhost,127.0.0.1 \
  nginx

Bạn cũng có thể truyền cả một file môi trường:

# proxy.env
HTTP_PROXY=http://proxy.company.com:8080
HTTPS_PROXY=http://proxy.company.com:8080
NO_PROXY=localhost,127.0.0.1

docker run --env-file proxy.env nginx

Container đang chạy có thể được tiêm biến proxy sau khi khởi động bằng docker exec:

docker exec -e HTTP_PROXY=http://proxy.company.com:8080 container_name curl google.com

Cách này phù hợp cho lệnh chạy tức thời nhưng không tồn tại sau khi container khởi động lại.

Cấu hình proxy lúc build

Build image sẽ thất bại trong môi trường proxy trừ khi bạn truyền cài đặt proxy một cách tường minh.

Build argument là cách tiêu chuẩn để tiêm biến proxy trong lúc build:

docker build \
  --build-arg HTTP_PROXY=http://proxy.company.com:8080 \
  --build-arg HTTPS_PROXY=http://proxy.company.com:8080 \
  --build-arg NO_PROXY=localhost,127.0.0.1 \
  --tag myapp .

Dockerfile của bạn cần khai báo các argument này để sử dụng chúng:

ARG HTTP_PROXY
ARG HTTPS_PROXY
ARG NO_PROXY

# Use proxy for package installation
RUN apt-get update && apt-get install -y curl

# Don't persist proxy in final image

Khai báo trong Dockerfile cho phép bạn đặt giá trị mặc định cho proxy:

ARG HTTP_PROXY=http://proxy.company.com:8080
ARG HTTPS_PROXY=http://proxy.company.com:8080

ENV HTTP_PROXY=$HTTP_PROXY
ENV HTTPS_PROXY=$HTTPS_PROXY

RUN pip install requests

Lệnh ENV giúp biến proxy khả dụng cho mọi lệnh RUN tiếp theo trong build.

Bạn cần lưu ý rằng các giới hạn của BuildKit có thể gây ra vấn đề proxy trên các phiên bản Docker mới. BuildKit cache ngữ cảnh build rất mạnh, đôi khi bỏ qua thay đổi proxy.

Bạn có thể buộc BuildKit nhận biết cập nhật proxy:

DOCKER_BUILDKIT=1 docker build \
  --no-cache \
  --build-arg HTTP_PROXY=$HTTP_PROXY \
  --tag myapp .

Hoặc, bạn có thể tắt hẳn BuildKit cho các bản build nhạy proxy:

DOCKER_BUILDKIT=0 docker build --build-arg HTTP_PROXY=$HTTP_PROXY --tag myapp .

Với multi-stage build, chúng cần cấu hình proxy nhất quán trên mọi stage:

ARG HTTP_PROXY
ARG HTTPS_PROXY
ARG NO_PROXY

# Build stage
FROM python:3.13 AS builder
ENV HTTP_PROXY=$HTTP_PROXY
ENV HTTPS_PROXY=$HTTPS_PROXY
ENV NO_PROXY=$NO_PROXY

COPY requirements.txt .
RUN pip install -r requirements.txt

# Runtime stage
FROM python:3.13-slim AS runtime
ENV HTTP_PROXY=$HTTP_PROXY
ENV HTTPS_PROXY=$HTTPS_PROXY
ENV NO_PROXY=$NO_PROXY

COPY --from=builder /usr/local/lib/python*/site-packages /usr/local/lib/python*/site-packages
RUN apt-get update && apt-get install -y curl

# Clear proxy variables for final image
ENV HTTP_PROXY=
ENV HTTPS_PROXY=
ENV NO_PROXY=

Mỗi stage kế thừa build argument nhưng không kế thừa biến môi trường từ stage trước. Hãy đặt biến proxy một cách tường minh ở mọi stage cần chúng.

Tóm lại - cấu hình một lần, tiêm ở mọi nơi.

Bối rối về ENTRYPOINT và CMD trong container có bật proxy? Xem phân tích đầy đủ kèm ví dụ thực tế.

Cấu hình Proxy cho Trình quản lý gói trong Container

Cài đặt proxy của Docker không tự động áp dụng xuống các trình quản lý gói bên trong container. Bạn cần cấu hình từng trình quản lý gói riêng để tải gói qua proxy doanh nghiệp.

Các trình quản lý gói như apt-get, yum và apk thực hiện kết nối HTTP trực tiếp đến các kho gói. Trong môi trường mạng hạn chế, các kết nối này sẽ thất bại trừ khi trình quản lý gói biết về máy chủ proxy của bạn.

Chỉ đặt biến môi trường là chưa đủ. Hầu hết trình quản lý gói có file cấu hình riêng ghi đè cài đặt proxy toàn hệ thống.

Ubuntu/Debian: cấu hình apt-get

Tạo một file cấu hình proxy mà apt-get sẽ đọc trong quá trình cài gói.

Thêm vào Dockerfile của bạn:

FROM python:3.13

# Configure apt proxy
RUN echo 'Acquire::http::Proxy "http://proxy.company.com:8080";' > /etc/apt/apt.conf.d/proxy.conf && \
    echo 'Acquire::https::Proxy "http://proxy.company.com:8080";' >> /etc/apt/apt.conf.d/proxy.conf

RUN apt-get update && apt-get install -y curl wget

File /etc/apt/apt.conf.d/proxy.conf yêu cầu apt-get định tuyến toàn bộ việc tải gói qua proxy. File này tồn tại xuyên suốt các lệnh RUN trong build.

Bạn cũng có thể đặt loại trừ proxy cho các kho nội bộ:

RUN echo 'Acquire::http::Proxy::internal.company.com "DIRECT";' >> /etc/apt/apt.conf.d/proxy.conf

Alpine Linux: cấu hình apk

Alpine dùng trình quản lý gói apk, vốn đọc cài đặt proxy từ /etc/apk/repositories và biến môi trường.

FROM python:3.13-alpine

# Configure apk proxy
ENV HTTP_PROXY=http://proxy.company.com:8080
ENV HTTPS_PROXY=http://proxy.company.com:8080

RUN apk add --no-cache curl wget

apk của Alpine tôn trọng các biến môi trường proxy HTTP tiêu chuẩn, vì vậy bạn không cần file cấu hình riêng. Nhưng bạn có thể tạo để kiểm soát nhiều hơn:

RUN echo 'http_proxy=http://proxy.company.com:8080' > /etc/environment && \
    echo 'https_proxy=http://proxy.company.com:8080' >> /etc/environment

CentOS/RHEL: cấu hình yum

Hệ CentOS và RHEL dùng yum hoặc dnf, đọc cài đặt proxy từ /etc/yum.conf.

FROM centos:8

# Configure yum proxy
RUN echo 'proxy=http://proxy.company.com:8080' >> /etc/yum.conf

RUN yum update -y && yum install -y curl wget

Với các phiên bản CentOS mới hơn dùng dnf, dùng lệnh sau:

FROM centos:stream9

# Configure dnf proxy
RUN echo 'proxy=http://proxy.company.com:8080' >> /etc/dnf/dnf.conf

RUN dnf update -y && dnf install -y curl wget

Bạn cũng có thể loại trừ một số domain khỏi định tuyến qua proxy bằng lệnh này:

RUN echo 'proxy_exclude=internal.company.com,localhost' >> /etc/yum.conf

Kiểm thử chức năng proxy

Trước tiên, bạn cần xác minh trình quản lý gói có thể đến được các kho qua proxy.

Thêm các lệnh kiểm thử vào Dockerfile:

FROM python:3.13

# Configure proxy
RUN echo 'Acquire::http::Proxy "http://proxy.company.com:8080";' > /etc/apt/apt.conf.d/proxy.conf

# Test package manager connectivity
RUN apt-get update && \
    apt-get install -y --dry-run curl && \
    echo "Package manager proxy test passed"

# Install actual packages
RUN apt-get install -y curl python3-pip

Cờ --dry-run kiểm thử việc phân giải gói mà không cài đặt gì. Nếu thành công, cấu hình proxy của bạn hoạt động.

Bạn cũng có thể kiểm thử với đầu ra chi tiết để gỡ lỗi kết nối:

RUN apt-get -o Debug::Acquire::http=true update

Lệnh này hiển thị chính xác các URL mà apt-get cố truy cập và kết nối qua proxy có thành công hay không.

Đối với Alpine, dùng các lệnh sau để kiểm thử:

RUN apk update --verbose && \
    apk add --simulate curl && \
    echo "Alpine proxy test passed"

Tóm lại, hãy cấu hình từng trình quản lý gói riêng lẻ, và bản build của bạn sẽ hoạt động sau bất kỳ proxy nào.

Cần dọn dẹp các tạo tác build liên quan proxy? Các lệnh docker prune sẽ giải phóng dung lượng và giữ hệ thống gọn gàng.

Triển khai Proxy nâng cao

Proxy HTTP cơ bản giúp bạn khởi đầu, nhưng môi trường production cần kiểm soát chặt chẽ hơn đối với truy cập registry và cache image. Dưới đây là cách thiết lập proxy cache và mirror registry để có hiệu năng và độ tin cậy tốt hơn.

Proxy cache cho registry

Lặp đi lặp lại việc kéo cùng base image gây lãng phí băng thông và làm chậm build.

Proxy cache nằm giữa Docker client của bạn và các registry bên ngoài như Docker Hub. Chúng lưu trữ cục bộ các image truy cập thường xuyên, vì thế các lần kéo sau sẽ đến từ mạng nội bộ thay vì internet.

Lựa chọn phổ biến nhất cho môi trường doanh nghiệp là Harbor:

# docker-compose.yml for Harbor
version: '3.8'
services:
  harbor-core:
    image: goharbor/harbor-core:v2.8.0
    environment:
      - CORE_SECRET=your-secret-key
      - JOBSERVICE_SECRET=your-job-secret
    ports:
      - "80:8080"
    volumes:
      - ./harbor.yml:/etc/core/app.conf

Bạn có thể cấu hình Harbor làm proxy cache bằng cách chỉnh harbor.yml:

# harbor.yml
hostname: harbor.company.com
http:
  port: 80

database:
  password: harbor-db-password

data_volume: /data

proxy_cache:
  - endpoint: https://registry-1.docker.io
    username: your-dockerhub-username
    password: your-dockerhub-token

Nếu bạn cần một lựa chọn đơn giản hơn để cache cơ bản, dùng Docker Registry Proxy. Cách làm như sau:

docker run -d \
  --name registry-proxy \
  -p 5000:5000 \
  -e REGISTRY_PROXY_REMOTEURL=https://registry-1.docker.io \
  -v registry-cache:/var/lib/registry \
  registry:2

Sau đó, trỏ các Docker client của bạn đến proxy cache:

{
  "registry-mirrors": ["http://harbor.company.com"]
}

Đây là các lợi ích bạn nhận được với proxy cache:

  • Tải image nhanh hơn sau lần đầu
  • Giảm sử dụng băng thông internet
  • Độ tin cậy build cao hơn khi registry bên ngoài gặp sự cố
  • Kiểm soát truy cập tập trung và quét image

Registry mirror và BuildKit

Registry mirror cho phép bạn chuyển hướng việc kéo image đến các registry nội bộ hoặc gần về mặt địa lý.

Cấu hình một mirror duy nhất sẽ định tuyến toàn bộ yêu cầu đến Docker Hub qua một mirror:

{
  "registry-mirrors": ["https://mirror.company.com"],
  "insecure-registries": ["harbor.company.com:5000"]
}

Thêm cấu hình này vào /etc/docker/daemon.json và khởi động lại Docker. Tất cả lệnh docker pull sẽ thử mirror trước, rồi mới quay lại Docker Hub nếu mirror không khả dụng.

Nhiều mirror tạo tính dự phòng:

{
  "registry-mirrors": [
    "https://mirror1.company.com",
    "https://mirror2.company.com",
    "https://registry-1.docker.io"
  ]
}

Docker sẽ thử các mirror theo thứ tự cho đến khi thành công.

Thiết lập mirror cho BuildKit cần cấu hình riêng vì BuildKit bỏ qua một số cài đặt của daemon:

# buildkitd.toml
debug = true

[registry."docker.io"]
  mirrors = ["mirror.company.com"]

[registry."mirror.company.com"]
  http = true
  insecure = true

Bạn có thể khởi động BuildKit với cấu hình tùy chỉnh:

buildkitd --config=/etc/buildkit/buildkitd.toml

Hoặc, dùng cấu hình mirror inline của BuildKit:

docker buildx create \
  --name mybuilder \
  --config /etc/buildkit/buildkitd.toml \
  --use

Cuối cùng, kiểm thử thiết lập mirror bằng cách build một image kéo từ Docker Hub:

FROM python:3.13-slim
RUN pip install requests
docker build --progress=plain .

Cờ --progress=plain hiển thị registry nào BuildKit thực sự liên hệ. Bạn nên thấy URL mirror của mình trong đầu ra build.

Vậy là xong!

Đang quản lý các thiết lập proxy đa-container phức tạp? Docker Compose giúp đơn giản hóa mạng và khám phá dịch vụ.

Tăng cường bảo mật

Cấu hình proxy mở ra các khả năng tấn công mới cần được chú ý kỹ. Dưới đây là cách khóa chặt quyền truy cập socket của Docker và bảo vệ thông tin xác thực proxy khỏi bị lộ.

Proxy cho Docker socket

Phơi bày trực tiếp Docker socket tạo rủi ro bảo mật nghiêm trọng.

Docker socket (/var/run/docker.sock) trao quyền truy cập cấp root tới toàn bộ hệ thống host của bạn. Bất kỳ tiến trình nào có thể ghi vào socket này đều có thể khởi tạo container truy cập filesystem của host, leo thang đặc quyền, hoặc phá vỡ hoàn toàn cơ chế cô lập container.

Gắn mount trực tiếp socket là nguy hiểm:

# DON'T DO THIS
docker run -v /var/run/docker.sock:/var/run/docker.sock myapp

Mẫu này xuất hiện trong thiết lập Docker-in-Docker và pipeline CI/CD, nhưng là cơn ác mộng bảo mật. Một container bị xâm nhập có thể điều khiển toàn bộ Docker daemon.

Dịch vụ socket proxy tạo một lớp trung gian an toàn hơn. Chúng lọc các lời gọi Docker API và hạn chế những gì container có thể thực sự làm.

Dùng docker-socket-proxy của Tecnativa:

# docker-compose.yml
version: '3.8'
services:
  docker-proxy:
    image: tecnativa/docker-socket-proxy
    environment:
      - CONTAINERS=1
      - IMAGES=1
      - NETWORKS=1
      - VOLUMES=1
      - BUILD=0
      - COMMIT=0
      - CONFIGS=0
      - SECRETS=0
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    ports:
      - "2375:2375"

Proxy chỉ phơi bày các endpoint Docker API cụ thể. Đặt biến môi trường thành 1 cho thao tác cho phép và 0 cho thao tác bị chặn.

Ứng dụng của bạn kết nối tới proxy thay vì socket thô:

docker run --env DOCKER_HOST=tcp://docker-proxy:2375 myapp

Dưới đây là một số chiến lược tăng cường bảo vệ socket nên thực hiện:

  • Chạy socket proxy trên một phân đoạn mạng riêng
  • Dùng xác thực TLS giữa client và proxy
  • Giám sát log của socket proxy để phát hiện lời gọi API đáng ngờ
  • Thường xuyên xoay vòng thông tin xác thực truy cập proxy

Quản lý thông tin xác thực

Thông tin xác thực proxy trong URL văn bản thuần sẽ xuất hiện ở mọi nơi - log, danh sách tiến trình, dump biến môi trường.

Không bao giờ nhúng thông tin xác thực trong URL proxy:

# SECURITY RISK - credentials visible in process list
export HTTP_PROXY=http://admin:[email protected]:8080

Bất kỳ ai có quyền truy cập ps aux hoặc dump biến môi trường đều có thể thấy mật khẩu proxy của bạn. Điều này bao gồm log ứng dụng, thông tin inspect container và các công cụ giám sát hệ thống.

Thay vào đó, dùng file xác thực:

# Create credentials file with restricted permissions
echo "admin:password123" > ~/.proxy-creds
chmod 600 ~/.proxy-creds

# Configure proxy without embedded credentials
export HTTP_PROXY=http://proxy.company.com:8080

Cấu hình máy chủ proxy để đọc thông tin xác thực từ file hoặc dùng các hệ thống xác thực bên ngoài.

Proxy dùng TLS mã hóa toàn bộ lưu lượng proxy bao gồm cả bắt tay xác thực:

# HTTPS proxy encrypts credentials in transit
export HTTPS_PROXY=https://proxy.company.com:8443

Thiết lập máy chủ proxy với chứng chỉ TLS phù hợp - từ CA hoặc chứng chỉ tự ký được phân phối tới các máy client.

Xác thực dựa trên chứng chỉ loại bỏ hoàn toàn mật khẩu:

# Client certificate authentication
export HTTPS_PROXY=https://proxy.company.com:8443
curl --cert client.crt --key client.key --cacert proxy-ca.crt https://example.com

Proxy xác thực chứng chỉ client thay cho cặp tên người dùng/mật khẩu. Có thể thu hồi chứng chỉ từng cái nếu bị lộ.

Quản lý secret trong Kubernetes giúp giữ thông tin xác thực proxy nằm ngoài image của container:

apiVersion: v1
kind: Secret
metadata:
  name: proxy-credentials
type: Opaque
data:
  username: YWRtaW4=  # base64 encoded
  password: cGFzc3dvcmQxMjM=  # base64 encoded
apiVersion: apps/v1
kind: Deployment
spec:
  template:
    spec:
      containers:
      - name: myapp
        env:
        - name: PROXY_USER
          valueFrom:
            secretKeyRef:
              name: proxy-credentials
              key: username
        - name: PROXY_PASS
          valueFrom:
            secretKeyRef:
              name: proxy-credentials
              key: password

Secret được mã hóa khi lưu trữ và được tiêm lúc chạy mà không xuất hiện trong các layer của image.

Hãy khóa chặt quyền truy cập socket và mã hóa thông tin xác thực của bạn - sau này bạn sẽ thấy biết ơn.

Cân nhắc các lựa chọn thay thế Docker cho thiết lập proxy của bạn? So sánh Docker và Podman để chọn công cụ đóng gói phù hợp.

Khắc phục sự cố thường gặp

Sự cố proxy biểu hiện dưới dạng timeout, lỗi kết nối và các lỗi build bí ẩn vốn chạy tốt ngoài mạng nội bộ. Dưới đây là cách tiếp cận có hệ thống để chẩn đoán và khắc phục các vấn đề proxy Docker thường gặp.

Cách chẩn đoán có cấu trúc

Bắt đầu từ những điều cơ bản và đi dần lên từng lớp.

Bước 1: Xác minh kết nối proxy từ host

Kiểm tra máy chủ proxy của bạn có thể truy cập được không:

curl -x http://proxy.company.com:8080 https://registry-1.docker.io/v2/

Nếu lệnh này thất bại, cấu hình proxy hoặc định tuyến mạng của bạn có vấn đề. Hãy liên hệ đội ngũ mạng trước khi khắc phục trên Docker.

Bước 2: Kiểm tra cài đặt proxy của Docker daemon

Xác minh daemon đọc được cấu hình proxy của bạn:

docker info | grep -i proxy

Bạn nên thấy URL proxy của mình được liệt kê. Nếu thiếu, kiểm tra /etc/docker/daemon.json và khởi động lại dịch vụ Docker.

Bước 3: Kiểm thử thao tác phía Docker client

Thử kéo một image đơn giản:

docker pull hello-world

Thành công nghĩa là cài đặt proxy phía client hoạt động. Thất bại cho thấy vấn đề ở cấp proxy của daemon.

Bước 4: Kiểm thử kết nối ở cấp container

Chạy một container và kiểm thử kết nối ra ngoài:

docker run --rm \
  -e HTTP_PROXY=http://proxy.company.com:8080 \
  -e HTTPS_PROXY=http://proxy.company.com:8080 \
  python:3.13-slim \
  python -c "import urllib.request; print(urllib.request.urlopen('https://pypi.org').getcode())"

Cách này cô lập xem vấn đề nằm ở thao tác Docker hay mạng của container.

Vấn đề thường gặp và cách giải quyết

Vấn đề: docker pull bị timeout

Bạn sẽ thấy lỗi này khi Docker không thể đến registry bên ngoài:

Error response from daemon: Get "https://registry-1.docker.io/v2/": dial tcp: lookup registry-1.docker.io: no such host

Bắt đầu bằng việc kiểm thử kết nối cơ bản để xác định vị trí xảy ra vấn đề:

# Check if DNS resolution works through proxy
nslookup registry-1.docker.io

# Test direct registry access
curl -I https://registry-1.docker.io/v2/

# Verify daemon proxy configuration
sudo journalctl -u docker.service | grep -i proxy

Khắc phục bằng cách xử lý vấn đề DNS và cấu hình proxy:

  • Thêm máy chủ DNS vào /etc/docker/daemon.json

  • Cấu hình NO_PROXY cho các máy chủ DNS nội bộ

  • Kiểm tra proxy có hỗ trợ phương thức HTTPS CONNECT hay không

Vấn đề: Cài gói thất bại trong lúc build

Trình quản lý gói bên trong container không thể truy cập kho, hiển thị lỗi như sau:

E: Failed to fetch http://archive.ubuntu.com/ubuntu/dists/jammy/Release

Kiểm thử kết nối của trình quản lý gói trực tiếp trong một container tạm:

# Test package manager connectivity in a running container
docker run -it --rm python:3.13 bash
apt-get update -o Debug::Acquire::http=true

Đầu ra chi tiết sẽ hiển thị chính xác nơi kết nối bị lỗi.

Khắc phục bằng cách cấu hình trình quản lý gói sử dụng proxy của bạn:

  • Cấu hình cài đặt proxy cho trình quản lý gói trong Dockerfile
  • Truyền build argument proxy cho Docker build
  • Kiểm tra proxy có chặn domain của kho gói hay không

Vấn đề: BuildKit bỏ qua cài đặt proxy

BuildKit xử lý proxy khác với builder cũ, gây ra lỗi như sau:

failed to solve: failed to fetch remote https://github.com/user/repo.git

Kiểm thử xem vấn đề có đặc thù BuildKit hay không bằng cách kiểm tra cấu hình builder:

# Check BuildKit configuration
docker buildx inspect

# Build with legacy builder
DOCKER_BUILDKIT=0 docker build .

Nếu builder cũ chạy được, bạn đang gặp vấn đề cấu hình proxy cho BuildKit.

Khắc phục vấn đề proxy của BuildKit bằng các cách sau:

  • Cấu hình cài đặt proxy riêng cho BuildKit trong buildkitd.toml
  • Dùng --build-arg để truyền biến proxy một cách tường minh
  • Tắt BuildKit cho các bản build nhạy cảm với proxy

Vấn đề: Container không thể đến dịch vụ bên ngoài

Ứng dụng bên trong container không kết nối được đến API bên ngoài:

requests.exceptions.ConnectionError: HTTPSConnectionPool(host='api.example.com', port=443)

Gỡ lỗi bằng cách kiểm thử kết nối từ bên trong container:

# Test from inside the container
docker exec container_name curl -v https://api.example.com

# Check container environment variables
docker exec container_name env | grep -i proxy

Lệnh này cho thấy biến proxy có mặt hay không và thử kết nối có thành công không.

Giải quyết vấn đề kết nối của container bằng cách đảm bảo cấu hình proxy phù hợp:

  • Truyền biến môi trường proxy lúc runtime
  • Cấu hình proxy riêng cho ứng dụng
  • Thêm điểm đích vào danh sách NO_PROXY

Phân tích log và kiểm thử kết nối

Log của Docker daemon cho thấy toàn bộ câu chuyện về thương lượng proxy và lỗi.

Trên các hệ thống dùng systemd, dùng journalctl để theo dõi log dịch vụ Docker theo thời gian thực:

# SystemD systems
sudo journalctl -u docker.service -f

Với hệ thống dùng file log truyền thống, kiểm tra trực tiếp log của Docker:

# Direct log file
sudo tail -f /var/log/docker.log

Tìm các mẫu liên quan đến proxy trong log. Lỗi connection refused cho thấy máy chủ proxy không truy cập được. Lỗi xác thực hiển thị dưới dạng thông điệp "407 Proxy Authentication Required". Lỗi timeout gợi ý vấn đề định tuyến mạng hoặc quá tải máy chủ proxy.

Kiểm thử ở cấp container với curl và wget cho bạn cái nhìn chi tiết về hành vi proxy.

Kiểm thử kết nối HTTP qua proxy để xem chính xác điều gì xảy ra trong quá trình bắt tay:

# Test HTTP proxy
docker run --rm \
  -e HTTP_PROXY=http://proxy.company.com:8080 \
  python:3.13-slim \
  curl -v http://httpbin.org/ip

Đầu ra chi tiết hiển thị phân giải DNS, thiết lập kết nối proxy và luồng request HTTP thực tế. Bạn sẽ thấy các dòng như "Connected to proxy.company.com" sau đó là "CONNECT httpbin.org:80" nếu đường hầm proxy hoạt động đúng.

Kết nối HTTPS yêu cầu proxy hỗ trợ phương thức CONNECT:

# Test HTTPS proxy
docker run --rm \
  -e HTTPS_PROXY=http://proxy.company.com:8080 \
  python:3.13-slim \
  curl -v https://httpbin.org/ip

Hãy chú ý "CONNECT httpbin.org:443 HTTP/1.1" trong đầu ra. Nếu thấy "Method not allowed" hoặc lỗi tương tự, proxy của bạn không hỗ trợ đường hầm HTTPS.

Kiểm thử xác thực bằng cách nhúng thông tin xác thực trong URL proxy:

# Test with authentication
docker run --rm \
  -e HTTPS_PROXY=http://user:[email protected]:8080 \
  python:3.13-slim \
  wget -O- https://httpbin.org/ip

Lỗi xác thực hiển thị dưới dạng phản hồi "407 Proxy Authentication Required". Xác thực thành công sẽ tiếp tục trực tiếp đến request đích.

Gỡ lỗi ở tầng mạng bằng tcpdump sẽ bắt các gói tin thực sự giữa Docker và máy chủ proxy của bạn.

Chạy tcpdump để xem toàn bộ lưu lượng chảy tới proxy của bạn:

# Capture proxy traffic
sudo tcpdump -i any host proxy.company.com and port 8080

Bản ghi thô này hiển thị các lần thử kết nối, truyền dữ liệu và kết thúc kết nối. Hãy tìm việc thiết lập kết nối TCP (gói SYN/ACK) tiếp theo là lưu lượng HTTP. Timeout kết nối xuất hiện dưới dạng lặp lại gói SYN không có phản hồi.

Kiểm thử phân giải DNS loại trừ một nguồn gốc gây nhầm lẫn phổ biến về proxy.

Nhiều vấn đề proxy thực chất là vấn đề DNS đội lốt. Kiểm thử phân giải DNS bên trong container:

# Test DNS inside containers  
docker run --rm python:3.13-slim nslookup registry-1.docker.io

Nếu lệnh này thất bại, container không thể phân giải tên miền. Hãy thử dùng máy chủ DNS công cộng để cô lập vấn đề:

# Test with custom DNS
docker run --dns 8.8.8.8 --rm python:3.13-slim nslookup registry-1.docker.io

Môi trường doanh nghiệp thường có máy chủ DNS chỉ hoạt động từ bên trong mạng. Proxy của bạn có thể cần xử lý cả yêu cầu DNS lẫn lưu lượng HTTP, hoặc bạn có thể cần cấu hình container dùng các máy chủ DNS cụ thể hoạt động qua proxy.

Làm việc lần lượt qua từng lớp một cách có hệ thống, và bạn sẽ tìm ra nguyên nhân gốc.

Đang tìm các lựa chọn có thể xử lý proxy theo cách khác biệt? Chúng tôi có hướng dẫn về các lựa chọn thay thế Docker để bạn khám phá bức tranh đầy đủ về công cụ đóng gói container trong năm 2025.

Kết luận

Cấu hình proxy cho Docker không chỉ là để tải image - mà còn là xây dựng ứng dụng đóng gói tin cậy, an toàn trong môi trường doanh nghiệp.

Tôi đã chỉ bạn cách cấu hình proxy ở bốn lớp: thao tác phía client, tiến trình daemon, runtime của container và thao tác lúc build. Mỗi lớp phục vụ một mục đích riêng và cần cách cấu hình đặc thù, từ file JSON và biến môi trường đến cài đặt của trình quản lý gói và cấu hình BuildKit. Chiến lược proxy theo lớp giúp bạn tránh điểm lỗi đơn lẻ.

Muốn đi sâu hơn về Docker, đóng gói container và bảo mật? Hãy xem danh sách khóa học chọn lọc của chúng tôi:

Dario Radečić

Tác giả

Dario Radečić

Chuyên gia Khoa học Dữ liệu Cấp cao, làm việc tại Croatia. Tác giả Công nghệ Hàng đầu với hơn 700 bài viết đã xuất bản, đạt trên 10 triệu lượt xem. Tác giả cuốn sách Tự động hóa Machine Learning với TPOT.

Câu hỏi thường gặp

Tại sao tôi cần cấu hình proxy cho Docker?

Mạng doanh nghiệp dùng máy chủ proxy để giám sát và lọc lưu lượng internet, điều này chặn kết nối trực tiếp của Docker tới các registry như Docker Hub. Nếu không cấu hình proxy đúng, bạn sẽ thấy timeout khi kéo image, build thất bại khi cài gói, và container không thể truy cập dịch vụ bên ngoài. Cài đặt proxy cho Docker định tuyến tất cả các kết nối này qua máy chủ proxy doanh nghiệp, giúp mọi thứ hoạt động trơn tru phía sau tường lửa.

Sự khác biệt giữa cài đặt proxy của Docker daemon và client là gì?

Docker daemon xử lý các thao tác như kéo và đẩy image tới registry, trong khi Docker client quản lý các lệnh CLI và lời gọi API. Mỗi bên cần cấu hình proxy riêng vì chúng thực hiện các loại yêu cầu mạng khác nhau. Thiếu một trong hai cấu hình sẽ tạo ra khoảng trống khiến một số thao tác Docker hoạt động còn số khác thất bại với lỗi kết nối.

Container có tự động kế thừa cài đặt proxy từ host không?

Không, container không mặc định kế thừa cài đặt proxy của host. Bạn cần truyền biến môi trường proxy một cách tường minh khi khởi chạy container bằng các cờ --env, file môi trường hoặc cấu hình JSON. Cơ chế tách biệt này cho phép bạn chạy container với cài đặt proxy khác nhau hoặc bỏ qua proxy hoàn toàn cho một số ứng dụng cụ thể.

Vì sao build Docker của tôi thất bại dù kéo image vẫn hoạt động?

Quá trình build Docker cần truyền cài đặt proxy dạng build argument vì quá trình build hoạt động tách biệt khỏi cấu hình client của bạn. Dùng --build-arg HTTP_PROXY=... khi chạy docker build, và khai báo các argument này trong Dockerfile với lệnh ARG. Trình quản lý gói bên trong container cũng cần file cấu hình proxy riêng để tải phụ thuộc.

Tôi khắc phục vấn đề proxy của BuildKit (không xảy ra với builder cũ) như thế nào?

BuildKit xử lý proxy khác và cache ngữ cảnh build rất mạnh, đôi khi bỏ qua thay đổi proxy. Hãy thử build với --no-cache để buộc phát hiện proxy mới, hoặc dùng DOCKER_BUILDKIT=0 để tắt BuildKit hoàn toàn. Với vấn đề kéo dài, hãy cấu hình proxy riêng cho BuildKit trong /etc/buildkit/buildkitd.toml với thiết lập mirror registry.

Chủ đề

Liên quan