最近在寫一個即時聊天程序的DEMO,技術棧差很少是vue+nodejs+redis+rabbitmq,裏面有用到rabbitmq來處理消息列隊,
程序寫好後,我用docker-compose作了個鏡像,往後好給別人作DEMO。
docker-compose.yml大體以下vue
version: "3" services: redis: image: redis:latest ports: - "6379:6379" container_name: im-redis-compose restart: always command: redis-server --appendonly yes rabbitmq: image: rabbitmq:management ports: - "5672:5672" - "15672:15672" container_name: im-rabbitmq-compose environment: RABBITMQ_DEFAULT_USER: guest RABBITMQ_DEFAULT_PASS: guest RABBITMQ_DEFAULT_VHOST: my_vhost backend: build: . links: - redis - rabbitmq container_name: im-server-compose restart: on-failure depends_on: - rabbitmq - redis ports: - "3000:3000"
因爲nodejs服務的啓動會和redis和rabbitmq創建connection,有依賴關係。因而我使用docker-compose中的depends_on
屬性來決定啓動順序,再用links
屬性來作docker容器內訪問的網絡別名,一切看起來都很順利。可是當我敲下docker-compose up
命令的時候卻報錯了。node
看了一下啓動log,nodejs先報的錯,啓動的時候報了connect refused,鏈接rabbitmq的時候出錯。git
im-server-compose | Error: connect ECONNREFUSED 172.24.0.3:5672 im-server-compose | at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1136:16) { im-server-compose | errno: -111, im-server-compose | code: 'ECONNREFUSED', im-server-compose | syscall: 'connect', im-server-compose | address: '172.24.0.3', im-server-compose | port: 5672 im-server-compose | } im-server-compose | npm ERR! code ELIFECYCLE im-server-compose | npm ERR! errno 1
接下來打印出了rabbitmq啓動成功的消息github
im-rabbitmq-compose | 2020-01-06 08:44:17.837 [info] <0.504.0> Management plugin: HTTP (non-TLS) listener started on port 15672 im-rabbitmq-compose | 2020-01-06 08:44:17.839 [info] <0.610.0> Statistics database started. im-rabbitmq-compose | 2020-01-06 08:44:17.839 [info] <0.609.0> Starting worker pool 'management_worker_pool' with 3 processes in it im-rabbitmq-compose | 2020-01-06 08:44:18.132 [info] <0.8.0> Server startup complete; 3 plugins started. im-rabbitmq-compose | * rabbitmq_management im-rabbitmq-compose | * rabbitmq_management_agent im-rabbitmq-compose | * rabbitmq_web_dispatch im-rabbitmq-compose | completed with 3 plugins.
咦!有點confused!明明設置了depends_on定了啓動順序,爲什麼rabbitmq尚未啓動徹底,就去跑nodejs的服務了?web
google找了半天,仍是沒有找到比較好的解決方案,浪費了不少時間。最後仍是去看了docker-compose文檔關於depends_on的章節,才順藤摸瓜找到解決方案redis
depends_on
does not wait for db and redis to be 「ready」 before starting web - only until they have been started. If you need to wait for a service to be ready, seeControlling startup order
for more on this problem and strategies for solving it.
depends_on
在啓動web這個容器前,並不會等待db和redis這個兩個容器進入ready狀態,而只是等到它們被啓動狀態了。 若是你須要等待直到某個依賴的服務進入ready狀態,須要看進一閱讀控制啓動順序
一文
連接我貼在這裏,具體內容能夠本身去看https://docs.docker.com/compose/startup-order/
我大體說下他提到的解決思路
就在容器啓動命令執行前,跑一個shell腳本,這個腳本會去訪問依賴的服務的頁面或者ping api來判斷底層的服務有沒有ready,隨後再去啓動真正的服務。裏面有個現成的解決方案sh腳本叫wait-for, 只須要下載這份shell而且在dockerfile里加上docker
RUN apt-get -q update && apt-get -qy install netcat
docker-compose.yml裏調用wait-for的command便可shell
version: "3" services: redis: image: redis:latest ports: - "6379:6379" container_name: im-redis-compose restart: always command: redis-server --appendonly yes rabbitmq: image: rabbitmq:management ports: - "5672:5672" - "15672:15672" container_name: im-rabbitmq-compose environment: RABBITMQ_DEFAULT_USER: guest RABBITMQ_DEFAULT_PASS: guest RABBITMQ_DEFAULT_VHOST: my_vhost backend: build: . links: - redis - rabbitmq container_name: im-server-compose restart: on-failure depends_on: - rabbitmq - redis ports: - "3000:3000" command: sh -c './wait-for.sh rabbitmq:15672 -- npm run start'
command: sh -c './wait-for.sh rabbitmq:15672 -- npm run start'這句意思,就是等rabbitmq:15672這個management管理頁面能夠訪問了以後,在去執行真正的nodejs啓動命令"npm run start"
很久沒有來sf寫專欄了,但願對你們有幫助!npm