Docker 中 expose 和 port 之間的區別

Isaac Tony 2023年1月30日
  1. Docker 中的 EXPOSE DockerFile 指令
  2. Docker Compose 埠
Docker 中 expose 和 port 之間的區別

在 Docker 中,當我們使用 docker createdocker run 建立容器後,我們可能希望我們的容器與外部服務或其他外部容器互動。我們需要向外部世界提供埠來實現這一點。

在本文中,我們將介紹兩種可以用來在 Docker 中公開埠的重要方法。我們還將討論如何將容器埠對映到主機埠以及方法的差異。

Docker 中的 EXPOSE DockerFile 指令

docker 檔案只是一個文字檔案,它指定使用 docker build 命令組裝映象的指令。其中包括 EXPOSE 指令。

EXPOSE 指令用於通知 Docker 我們正在構建的容器應該在執行時監聽特定的網路埠。但是請注意,該指令只是一個參考點,並沒有將容器埠對映到主機埠。

語法:

EXPOSE <port>/<protocol>

我們不必指定協議,因為 Docker 可以使用預設的 TCP 協議。但是,我們可以提供其他協議,例如 UDP 協議。

Docker 將使用預設的 TCP 協議,因為 Nginx 官方 docker 檔案中沒有指定該協議。

COPY docker-entrypoint.sh /
COPY 10-listen-on-ipv6-by-default.sh /docker-entrypoint.d
COPY 20-envsubst-on-templates.sh /docker-entrypoint.d
COPY 30-tune-worker-processes.sh /docker-entrypoint.d
ENTRYPOINT ["/docker-entrypoint.sh"]
EXPOSE 80
STOPSIGNAL SIGQUIT
CMD ["nginx", "-g", "daemon off;"]

假設我們從 Docker 註冊中心拉取官方 Nginx 映象,建立一個容器,並執行該容器。在這種情況下,我們可以從容器中快速確定一些有用的資訊,例如埠號和使用的協議。

~/isaac$ docker ps -a

輸出:

CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS     NAMES
99edfdea0443   nginx     "/docker-entrypoint.…"   3 minutes ago   Up 2 minutes   80/tcp    nice_volhard

上面的輸出顯示 Nginx 容器在 Dockerfile 和 TCP 協議中所述的埠 80 上執行。

或者,我們也可以在建立容器時使用 --expose 標籤在執行時公開埠,如下所示。

docker run --expose 80 nginx

現在,將此埠繫結到主機埠號。我們需要使用大寫的 -P 標籤或小寫的 -p 標籤。

儘管我們可以使用其中任何一個來獲得結果,但這些標籤有很大的不同。

大寫的 -P 標籤,當在執行時使用時,允許我們將所有暴露的標籤繫結到主機上的隨機埠。這使我們能夠避免埠衝突。

$ docker run -d -P nginx
006b88a06e51eac45895f13b33a89221676029e8fa654aaaccc79b81f74efb4d

程式碼:

isaac$ docker ps -a
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS         PORTS                   NAMES
006b88a06e51   nginx     "/docker-entrypoint.…"   27 seconds ago   Up 6 seconds   0.0.0.0:49153->80/tcp   angry_babbage

我們還可以使用小寫的 -p 標籤將容器釋出到主機上的特定埠。

Docker Compose 埠

Docker-compose 是一個實用工具,它允許我們在 Docker 上執行多容器應用程式。

docker-compose.yml 檔案下,我們可以指定容器在其他檔案中的配置方式,例如服務、檔案版本、使用的卷以及連線服務的網路。

就像我們在 Dockerfile 中指定埠號一樣,我們也需要在 docker-compose.yml 檔案中指定埠號。我們可以使用 exposeports 指令來做到這一點。

rabbitmq:
   image: rabbitmq
   expose: 
        - 3000
        - 5000

expose 指令允許我們在不釋出埠或將它們繫結到主機埠的情況下公開埠,即埠不暴露給主機,只暴露給其他服務。

另一方面,ports 指令允許我們指定主機和容器埠號。此外,這些埠將在其他服務之間共享,並向主機暴露給隨機或給定的埠。

rabbitmq:
   image: rabbitmq
   ports: 
        - "8000:80"
        - "5000: 70"
作者: Isaac Tony
Isaac Tony avatar Isaac Tony avatar

Isaac Tony is a professional software developer and technical writer fascinated by Tech and productivity. He helps large technical organizations communicate their message clearly through writing.

LinkedIn