国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 操作系統 > 正文

Docker Compose構建開發環境的好方式

2024-07-26 00:27:14
字體:
來源:轉載
供稿:網友
  最近,我考慮了很多關于這種個人開發環境的搭建方式,原因是,我現在把所有的計算工作都搬到了一個私有云上,大概 20 美元/月的樣子。這樣一來,我就不用在工作的時候花時間去思考應該如何管理幾千臺 AWS 服務器了。
 
  在此之前,我曾花了兩天的時間,嘗試使用其他的工具來嘗試搭建一個開發環境,搭到后面,我實在是心累了。相比起來,Docker Compose 就簡單易用多了,我非常滿意。于是,我和妹妹分享了我的 ​​docker-compose​​ 使用經歷,她略顯驚訝:“是吧!你也覺得 Docker Compose 真棒對吧!” 嗯,我覺得我應該寫一篇博文把過程記錄下來,于是就有了你們看到的這篇文章。
 
  我們的目標是:搭建一個開發環境
  目前,我正在編寫一個 Ruby on Rails 服務(它是一個計算機“調試”游戲的后端)。在我的生產服務器上,我安裝了:
 
  一個 Nginx 服務器
  一個 Rails 服務
  一個 Go 服務(使用了​​gotty​​ 來代理一些 SSH 連接)
  一個 Postgres 數據庫
  在本地搭建 Rails 服務非常簡單,用不著容器(我只需要安裝 Postgres 和 Ruby 就行了,小菜一碟)。但是,我還想要把匹配 ​​/proxy/*​​ 的請求的發送到 Go 服務,其他所有請求都發送到 Rails 服務,所以需要借助 Nginx。問題來了,在筆記本電腦上安裝 Nginx 對我來說太麻煩了。
 
  是時候使用 ​​docker-compose​​ 了!
 
  docker-compose 允許你運行一組 Docker 容器
  基本上,Docker Compose 的作用就是允許你運行一組可以互相通信 Docker 容器。
 
  你可以在一個叫做 ​​docker-compose.yml​​​ 的文件中,配置你所有的容器。我在下方將貼上我為這個服務編寫的 ​​docker-compose.yml​​ 文件(完整內容),因為我覺得它真的很簡潔、直接!
 
  復制
  version: "3.3"
      services:
        db:
          image: postgres
          volumes:
            - ./tmp/db:/var/lib/postgresql/data
          environment:
            POSTGRES_PASSWORD: password # yes I set the password to 'password'
        go_server:
          # todo: use a smaller image at some point, we don't need all of ubuntu to run a static go binary
          image: ubuntu
          command: /app/go_proxy/server
          volumes:
            - .:/app
        rails_server:
          build: docker/rails
          command: bash -c "rm -f tmp/pids/server.pid && source secrets.sh && bundle exec rails s -p 3000 -b '0.0.0.0'"
          volumes:
            - .:/app
        web:
          build: docker/nginx
          ports:
            - "8777:80" # this exposes port 8777 on my laptop
  1.
  2.
  3.
  4.
  5.
  6.
  7.
  8.
  9.
  10.
  11.
  12.
  13.
  14.
  15.
  16.
  17.
  18.
  19.
  20.
  21.
  22.
  23.
  這個配置包含了兩種容器。對于前面兩個容器,我直接使用了現有的鏡像(​​image: postgres​​​ 和 ​​image: ubuntu​​​)。對于后面兩個容器,我不得不構建一個自定義容器鏡像,其中, ​​build: docker/rails​​​ 的作用就是告訴 Docker Compose,它應該使用 ​​docker/rails/Dockerfile​​ 來構建一個自定義容器。
 
  我需要允許我的 Rails 服務訪問一些 API 密鑰和其他東西,因此,我使用了 ​​source secrets.sh​​,它的作用就是在環境變量中預設一組密鑰。
 
  如何啟動所有服務:先 “build” 后 “up”
  我一直都是先運行 ​​docker-compose build​​​ 來構建容器,然后再運行 ​​docker-compose up​​ 把所有服務啟動起來。
 
  你可以在 yaml 文件中設置 ​​depends_on​​,從而進行更多啟動容器的控制。不過,對于我的這些服務而言,啟動順序并不重要,所以我沒有設置它。
 
  網絡互通也非常簡單
  容器之間的互通也是一件很重要的事情。Docker Compose 讓這件事變得超級簡單!假設我有一個 Rails 服務正在名為 ​​rails_server​​​ 的容器中運行,端口是 3000,那么我就可以通過 ​​http://rails_server:3000​​ 來訪問該服務。就是這么簡單!
 
  以下代碼片段截取自我的 Nginx 配置文件,它是根據我的使用需求配置的(我刪除了許多 ​​proxy_set_headers​​ 行,讓它看起來更清楚):
 
  復制
  location ~ /proxy.* {
        proxy_pass http://go_server:8080;
      }
      location @app {
        proxy_pass http://rails_server:3000;
      }
  1.
  2.
  3.
  4.
  5.
  6.
  或者,你可以參考如下代碼片段,它截取自我的 Rails 項目的數據庫配置,我在其中使用了數據庫容器的名稱(​​db​​):
 
  復制
  development:
        <<: *default
        database: myproject_development
        host: db # <-------- 它會被“神奇地”解析為數據庫容器的 IP 地址
        username: postgres
        password: password
  1.
  2.
  3.
  4.
  5.
  6.
  至于 ​​rails_server​​ 究竟是如何被解析成一個 IP 地址的,我還真有點兒好奇。貌似是 Docker 在我的計算機上運行了一個 DNS 服務來解析這些名字。下面是一些 DNS 查詢記錄,我們可以看到,每個容器都有它自己的 IP 地址:
 
  復制
  $ dig +short @127.0.0.11 rails_server
      172.18.0.2
      $ dig +short @127.0.0.11 db
      172.18.0.3
      $ dig +short @127.0.0.11 web
      172.18.0.4
      $ dig +short @127.0.0.11 go_server
      172.18.0.5
  1.
  2.
  3.
  4.
  5.
  6.
  7.
  8.
  是誰在運行這個 DNS 服務?
  我(稍微)研究了一下這個 DNS 服務是怎么搭建起來的。
 
  以下所有命令都是在容器外執行的,因為我沒有在容器里安裝很多網絡工具。
 
  第一步::使用 ​​ps aux | grep puma​​,獲取 Rails 服務的進程 ID。
 
  找到了,它是 ​​1837916​​!簡單~
 
  第二步::找到和 ​​1837916​​ 運行在同一個網絡命名空間的 UDP 服務。
 
  我使用了 ​​nsenter​​​ 來在 ​​puma​​​ 進程的網絡命令空間內運行 ​​netstat​​​(理論上,我猜想你也可以使用 ​​netstat -tupn​​​ 來只顯示 UDP 服務,但此時,我的手指頭只習慣于打出 ​​netstat -tulpn​​)。
 
  復制
  $ sudo nsenter -n -t 1837916 netstat -tulpn
      Active Internet connections (only servers)
      Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
      tcp        0      0 127.0.0.11:32847        0.0.0.0:*               LISTEN      1333/dockerd
      tcp        0      0 0.0.0.0:3000            0.0.0.0:*               LISTEN      1837916/puma 4.3.7
      udp        0      0 127.0.0.11:59426        0.0.0.0:*                           1333/dockerd
  1.
  2.
  3.
  4.
  5.
  6.
  我們可以看到,此時有一個運行在 ​​59426​​​ 端口的 UDP 服務,它是由 ​​dockerd​​ 運行的!或許它就是我們要找的 DNS 服務?
 
  第三步:確定它是不是我們要找的 DNS 服務
 
  我們可以使用 ​​dig​​ 工具來向它發送一個 DNS 查詢:
 
  復制
  $ sudo nsenter -n -t 1837916 dig +short @127.0.0.11 59426 rails_server
      172.18.0.2
  1.
  2.
  奇怪,我們之前運行 ​​dig​​​ 的時候,DNS 查詢怎么沒有發送到 ​​59426​​​ 端口,而是發送到了 ​​53​​ 端口呢?這到底是怎么回事呀?
 
  第四步:iptables
 
  對于類似“這個服務似乎正運行在 X 端口上,但我卻在 Y 端口上訪問到了它,這是什么回事呢?”的問題,我的第一念頭都是“一定是 iptables 在作怪”。
 
  于是,我在運行了容器的網絡命令空間內執行 ​​iptables-save​​,果不其然,真相大白:
 
  復制
  $ sudo nsenter -n -t 1837916 iptables-save
      .... redacted a bunch of output ....
      -A DOCKER_POSTROUTING -s 127.0.0.11/32 -p udp -m udp --sport 59426 -j SNAT --to-source :53
      COMMIT
  1.
  2.
  3.
  4.
  在輸出中有一條 iptables 規則,它將 ​​53​​​ 端口的流量發送到了 ​​59426​​ 上。哈哈,真有意思!
 
  數據庫文件儲存在一個臨時目錄中
  這樣做有一個好處:我可以直接掛載 Postgres 容器的數據目錄 ​​./tmp/db​​,而無需在我的筆記本電腦上管理 Postgres 環境。
 
  我很喜歡這種方式,因為我真的不想在筆記本電腦上獨自管理一個 Postgres 環境(我也真的不知道該如何配置 Postgres)。另外,出于習慣,我更喜歡讓開發環境的數據庫和代碼放在同一個目錄下。
 
  僅需一行命令,我就可以訪問 Rails 控制臺
  管理 Ruby 的版本總是有點棘手,并且,即使我暫時搞定了它,我也總是有點擔心自己會把 Ruby 環境搞壞,然后就要修它個十年(夸張)。
 
  (使用 Docker Compose)搭建好這個開發環境后,如果我需要訪問 Rails 控制臺console(一個交互式環境,加載了所有我的 Rails 代碼),我只需要運行一行代碼即可:
 
  復制
  $ docker-compose exec rails_server rails console
      Running via Spring preloader in process 597
      Loading development environment (Rails 6.0.3.4)
      irb(main):001:0>
  1.
  2.
  3.
  4.
  好耶!
 
  小問題:Rails 控制臺的歷史記錄丟失了
  我碰到了一個問題:Rails 控制臺的歷史記錄丟失了,因為我一直在不斷地重啟它。
 
  不過,我也找到了一個相當簡單的解決方案(嘿嘿):我往容器中添加了一個 ​​/root/.irbrc​​ 文件,它能夠把 IRB 歷史記錄文件的保存位置指向一個不受容器重啟影響的地方。只需要一行代碼就夠啦:
 
  復制
  IRB.conf[:HISTORY_FILE] = "/app/tmp/irb_history"
  1.
  我還是不知道它在生產環境的表現如何
  到目前為止,這個項目的生產環境搭建進度,還停留在“我制作了一個 DigitalOcean droplet(LCCT 譯注:一種 Linux 虛擬機服務),并手工編輯了很多文件”的階段。
 
  嗯……我相信以后會在生產環境中使用 docker-compose 來運行一下它的。我猜它能夠正常工作,因為這個服務很可能最多只有兩個用戶在使用,并且,如果我愿意,我可以容忍它在部署過程中有 60 秒的不可用時間。不過話又說回來,出錯的往往是我想不到的地方。
 
  推特網友提供了一些在生產中使用 docker-compose 的注意事項:
 
  ​​docker-compose up​​ 只會重啟那些需要重啟的容器,這會讓重啟速度更快。
  有一個 Bash 小腳本​​wait-for-it​​,你可以用它來保持等待一個容器,直到另一個容器的服務可用。
  你可以準備兩份​​docker-compose.yaml​​​ 文件:用于開發環境的​​docker-compose.yaml​​​ 和用于生產環境的​​docker-compose-prod.yaml​​​。我想我會在分別為 Nginx 指定不同的端口:開發時使用​​8999​​​,生產中使用​​80​​。
  人們似乎一致認為,如果你的項目是一臺計算機上運行的小網站,那么 docker-compose 在生產中不會有問題。
  有個人建議說,如果愿意在生產環境搭建復雜那么一丟丟,Docker Swarm 就或許會是更好的選擇,不過我還沒試過(當然,如果要這么說的話,干嘛不用 Kubernetes 呢?Docker Compose 的意義就是它超級簡單,而 Kubernetes 肯定不簡單 : ))。
  Docker 似乎還有一個特性,它能夠 ​​把你用 docker-compose 搭建的環境,自動推送到彈性容器服務(ESC)上​​,聽上去好酷的樣子,但是我還沒有試過。
 
  docker-compose 會有不適用的場景嗎
  我聽說 docker-compose 在以下場景的表現較差:
 
  當你有很多微服務的時候(還是自己搭建比較好)
  當你嘗試從一個很大的數據庫中導入數據時(就像把幾百 G 的數據存到每個人的筆記本電腦里一樣)
  當你在 Mac 電腦上運行 Docker 時。我聽說 Docker 在 macOS 上比在 Linux 上要慢很多(我猜想是因為它需要做額外的虛擬化)。我沒有 Mac 電腦,所以我還沒有碰到這個問題。
  以上就是全部內容啦!
  在此之前,我曾花了一整天時間,嘗試使用 Puppet 來配置 Vagrant 虛擬機,然后在這個虛擬機里配置開發環境。結果,我發現虛擬機啟動起來實在是有點慢啊,還有就是,我也不喜歡編寫 Puppet 配置(哈哈,沒想到吧)。
 
  幸好,我嘗試了 Docker Compose,它真好簡單,馬上就可以開始工作啦!

(編輯:武林網)

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 咸丰县| 宁陵县| 合水县| 涞源县| 汽车| 奉化市| 常德市| 土默特右旗| 蒙阴县| 太和县| 福州市| 香港 | 敦化市| 武陟县| 平阴县| 库尔勒市| 武宁县| 义马市| 修水县| 密山市| 灌阳县| 饶阳县| 文昌市| 斗六市| 无极县| 页游| 蒲江县| 兰考县| 庆元县| 昔阳县| 英超| 全州县| 金山区| 清流县| 普定县| 图木舒克市| 比如县| 濮阳县| 基隆市| 彩票| 花垣县|