a亚洲精品_精品国产91乱码一区二区三区_亚洲精品在线免费观看视频_欧美日韩亚洲国产综合_久久久久久久久久久成人_在线区

首頁(yè) > 學(xué)院 > 操作系統(tǒng) > 正文

Docker Compose構(gòu)建開(kāi)發(fā)環(huán)境的好方式

2024-07-26 00:27:14
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友
  最近,我考慮了很多關(guān)于這種個(gè)人開(kāi)發(fā)環(huán)境的搭建方式,原因是,我現(xiàn)在把所有的計(jì)算工作都搬到了一個(gè)私有云上,大概 20 美元/月的樣子。這樣一來(lái),我就不用在工作的時(shí)候花時(shí)間去思考應(yīng)該如何管理幾千臺(tái) AWS 服務(wù)器了。
 
  在此之前,我曾花了兩天的時(shí)間,嘗試使用其他的工具來(lái)嘗試搭建一個(gè)開(kāi)發(fā)環(huán)境,搭到后面,我實(shí)在是心累了。相比起來(lái),Docker Compose 就簡(jiǎn)單易用多了,我非常滿意。于是,我和妹妹分享了我的 ​​docker-compose​​ 使用經(jīng)歷,她略顯驚訝:“是吧!你也覺(jué)得 Docker Compose 真棒對(duì)吧!” 嗯,我覺(jué)得我應(yīng)該寫(xiě)一篇博文把過(guò)程記錄下來(lái),于是就有了你們看到的這篇文章。
 
  我們的目標(biāo)是:搭建一個(gè)開(kāi)發(fā)環(huán)境
  目前,我正在編寫(xiě)一個(gè) Ruby on Rails 服務(wù)(它是一個(gè)計(jì)算機(jī)“調(diào)試”游戲的后端)。在我的生產(chǎn)服務(wù)器上,我安裝了:
 
  一個(gè) Nginx 服務(wù)器
  一個(gè) Rails 服務(wù)
  一個(gè) Go 服務(wù)(使用了​​gotty​​ 來(lái)代理一些 SSH 連接)
  一個(gè) Postgres 數(shù)據(jù)庫(kù)
  在本地搭建 Rails 服務(wù)非常簡(jiǎn)單,用不著容器(我只需要安裝 Postgres 和 Ruby 就行了,小菜一碟)。但是,我還想要把匹配 ​​/proxy/*​​ 的請(qǐng)求的發(fā)送到 Go 服務(wù),其他所有請(qǐng)求都發(fā)送到 Rails 服務(wù),所以需要借助 Nginx。問(wèn)題來(lái)了,在筆記本電腦上安裝 Nginx 對(duì)我來(lái)說(shuō)太麻煩了。
 
  是時(shí)候使用 ​​docker-compose​​ 了!
 
  docker-compose 允許你運(yùn)行一組 Docker 容器
  基本上,Docker Compose 的作用就是允許你運(yùn)行一組可以互相通信 Docker 容器。
 
  你可以在一個(gè)叫做 ​​docker-compose.yml​​​ 的文件中,配置你所有的容器。我在下方將貼上我為這個(gè)服務(wù)編寫(xiě)的 ​​docker-compose.yml​​ 文件(完整內(nèi)容),因?yàn)槲矣X(jué)得它真的很簡(jiǎn)潔、直接!
 
  復(fù)制
  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.
  這個(gè)配置包含了兩種容器。對(duì)于前面兩個(gè)容器,我直接使用了現(xiàn)有的鏡像(​​image: postgres​​​ 和 ​​image: ubuntu​​​)。對(duì)于后面兩個(gè)容器,我不得不構(gòu)建一個(gè)自定義容器鏡像,其中, ​​build: docker/rails​​​ 的作用就是告訴 Docker Compose,它應(yīng)該使用 ​​docker/rails/Dockerfile​​ 來(lái)構(gòu)建一個(gè)自定義容器。
 
  我需要允許我的 Rails 服務(wù)訪問(wèn)一些 API 密鑰和其他東西,因此,我使用了 ​​source secrets.sh​​,它的作用就是在環(huán)境變量中預(yù)設(shè)一組密鑰。
 
  如何啟動(dòng)所有服務(wù):先 “build” 后 “up”
  我一直都是先運(yùn)行 ​​docker-compose build​​​ 來(lái)構(gòu)建容器,然后再運(yùn)行 ​​docker-compose up​​ 把所有服務(wù)啟動(dòng)起來(lái)。
 
  你可以在 yaml 文件中設(shè)置 ​​depends_on​​,從而進(jìn)行更多啟動(dòng)容器的控制。不過(guò),對(duì)于我的這些服務(wù)而言,啟動(dòng)順序并不重要,所以我沒(méi)有設(shè)置它。
 
  網(wǎng)絡(luò)互通也非常簡(jiǎn)單
  容器之間的互通也是一件很重要的事情。Docker Compose 讓這件事變得超級(jí)簡(jiǎn)單!假設(shè)我有一個(gè) Rails 服務(wù)正在名為 ​​rails_server​​​ 的容器中運(yùn)行,端口是 3000,那么我就可以通過(guò) ​​http://rails_server:3000​​ 來(lái)訪問(wèn)該服務(wù)。就是這么簡(jiǎn)單!
 
  以下代碼片段截取自我的 Nginx 配置文件,它是根據(jù)我的使用需求配置的(我刪除了許多 ​​proxy_set_headers​​ 行,讓它看起來(lái)更清楚):
 
  復(fù)制
  location ~ /proxy.* {
        proxy_pass http://go_server:8080;
      }
      location @app {
        proxy_pass http://rails_server:3000;
      }
  1.
  2.
  3.
  4.
  5.
  6.
  或者,你可以參考如下代碼片段,它截取自我的 Rails 項(xiàng)目的數(shù)據(jù)庫(kù)配置,我在其中使用了數(shù)據(jù)庫(kù)容器的名稱(​​db​​):
 
  復(fù)制
  development:
        <<: *default
        database: myproject_development
        host: db # <-------- 它會(huì)被“神奇地”解析為數(shù)據(jù)庫(kù)容器的 IP 地址
        username: postgres
        password: password
  1.
  2.
  3.
  4.
  5.
  6.
  至于 ​​rails_server​​ 究竟是如何被解析成一個(gè) IP 地址的,我還真有點(diǎn)兒好奇。貌似是 Docker 在我的計(jì)算機(jī)上運(yùn)行了一個(gè) DNS 服務(wù)來(lái)解析這些名字。下面是一些 DNS 查詢記錄,我們可以看到,每個(gè)容器都有它自己的 IP 地址:
 
  復(fù)制
  $ 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.
  是誰(shuí)在運(yùn)行這個(gè) DNS 服務(wù)?
  我(稍微)研究了一下這個(gè) DNS 服務(wù)是怎么搭建起來(lái)的。
 
  以下所有命令都是在容器外執(zhí)行的,因?yàn)槲覜](méi)有在容器里安裝很多網(wǎng)絡(luò)工具。
 
  第一步::使用 ​​ps aux | grep puma​​,獲取 Rails 服務(wù)的進(jìn)程 ID。
 
  找到了,它是 ​​1837916​​!簡(jiǎn)單~
 
  第二步::找到和 ​​1837916​​ 運(yùn)行在同一個(gè)網(wǎng)絡(luò)命名空間的 UDP 服務(wù)。
 
  我使用了 ​​nsenter​​​ 來(lái)在 ​​puma​​​ 進(jìn)程的網(wǎng)絡(luò)命令空間內(nèi)運(yùn)行 ​​netstat​​​(理論上,我猜想你也可以使用 ​​netstat -tupn​​​ 來(lái)只顯示 UDP 服務(wù),但此時(shí),我的手指頭只習(xí)慣于打出 ​​netstat -tulpn​​)。
 
  復(fù)制
  $ 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.
  我們可以看到,此時(shí)有一個(gè)運(yùn)行在 ​​59426​​​ 端口的 UDP 服務(wù),它是由 ​​dockerd​​ 運(yùn)行的!或許它就是我們要找的 DNS 服務(wù)?
 
  第三步:確定它是不是我們要找的 DNS 服務(wù)
 
  我們可以使用 ​​dig​​ 工具來(lái)向它發(fā)送一個(gè) DNS 查詢:
 
  復(fù)制
  $ sudo nsenter -n -t 1837916 dig +short @127.0.0.11 59426 rails_server
      172.18.0.2
  1.
  2.
  奇怪,我們之前運(yùn)行 ​​dig​​​ 的時(shí)候,DNS 查詢?cè)趺礇](méi)有發(fā)送到 ​​59426​​​ 端口,而是發(fā)送到了 ​​53​​ 端口呢?這到底是怎么回事呀?
 
  第四步:iptables
 
  對(duì)于類似“這個(gè)服務(wù)似乎正運(yùn)行在 X 端口上,但我卻在 Y 端口上訪問(wèn)到了它,這是什么回事呢?”的問(wèn)題,我的第一念頭都是“一定是 iptables 在作怪”。
 
  于是,我在運(yùn)行了容器的網(wǎng)絡(luò)命令空間內(nèi)執(zhí)行 ​​iptables-save​​,果不其然,真相大白:
 
  復(fù)制
  $ 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 規(guī)則,它將 ​​53​​​ 端口的流量發(fā)送到了 ​​59426​​ 上。哈哈,真有意思!
 
  數(shù)據(jù)庫(kù)文件儲(chǔ)存在一個(gè)臨時(shí)目錄中
  這樣做有一個(gè)好處:我可以直接掛載 Postgres 容器的數(shù)據(jù)目錄 ​​./tmp/db​​,而無(wú)需在我的筆記本電腦上管理 Postgres 環(huán)境。
 
  我很喜歡這種方式,因?yàn)槲艺娴牟幌朐诠P記本電腦上獨(dú)自管理一個(gè) Postgres 環(huán)境(我也真的不知道該如何配置 Postgres)。另外,出于習(xí)慣,我更喜歡讓開(kāi)發(fā)環(huán)境的數(shù)據(jù)庫(kù)和代碼放在同一個(gè)目錄下。
 
  僅需一行命令,我就可以訪問(wèn) Rails 控制臺(tái)
  管理 Ruby 的版本總是有點(diǎn)棘手,并且,即使我暫時(shí)搞定了它,我也總是有點(diǎn)擔(dān)心自己會(huì)把 Ruby 環(huán)境搞壞,然后就要修它個(gè)十年(夸張)。
 
  (使用 Docker Compose)搭建好這個(gè)開(kāi)發(fā)環(huán)境后,如果我需要訪問(wèn) Rails 控制臺(tái)console(一個(gè)交互式環(huán)境,加載了所有我的 Rails 代碼),我只需要運(yùn)行一行代碼即可:
 
  復(fù)制
  $ 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.
  好耶!
 
  小問(wèn)題:Rails 控制臺(tái)的歷史記錄丟失了
  我碰到了一個(gè)問(wèn)題:Rails 控制臺(tái)的歷史記錄丟失了,因?yàn)槲乙恢痹诓粩嗟刂貑⑺?br /> 
  不過(guò),我也找到了一個(gè)相當(dāng)簡(jiǎn)單的解決方案(嘿嘿):我往容器中添加了一個(gè) ​​/root/.irbrc​​ 文件,它能夠把 IRB 歷史記錄文件的保存位置指向一個(gè)不受容器重啟影響的地方。只需要一行代碼就夠啦:
 
  復(fù)制
  IRB.conf[:HISTORY_FILE] = "/app/tmp/irb_history"
  1.
  我還是不知道它在生產(chǎn)環(huán)境的表現(xiàn)如何
  到目前為止,這個(gè)項(xiàng)目的生產(chǎn)環(huán)境搭建進(jìn)度,還停留在“我制作了一個(gè) DigitalOcean droplet(LCCT 譯注:一種 Linux 虛擬機(jī)服務(wù)),并手工編輯了很多文件”的階段。
 
  嗯……我相信以后會(huì)在生產(chǎn)環(huán)境中使用 docker-compose 來(lái)運(yùn)行一下它的。我猜它能夠正常工作,因?yàn)檫@個(gè)服務(wù)很可能最多只有兩個(gè)用戶在使用,并且,如果我愿意,我可以容忍它在部署過(guò)程中有 60 秒的不可用時(shí)間。不過(guò)話又說(shuō)回來(lái),出錯(cuò)的往往是我想不到的地方。
 
  推特網(wǎng)友提供了一些在生產(chǎn)中使用 docker-compose 的注意事項(xiàng):
 
  ​​docker-compose up​​ 只會(huì)重啟那些需要重啟的容器,這會(huì)讓重啟速度更快。
  有一個(gè) Bash 小腳本​​wait-for-it​​,你可以用它來(lái)保持等待一個(gè)容器,直到另一個(gè)容器的服務(wù)可用。
  你可以準(zhǔn)備兩份​​docker-compose.yaml​​​ 文件:用于開(kāi)發(fā)環(huán)境的​​docker-compose.yaml​​​ 和用于生產(chǎn)環(huán)境的​​docker-compose-prod.yaml​​​。我想我會(huì)在分別為 Nginx 指定不同的端口:開(kāi)發(fā)時(shí)使用​​8999​​​,生產(chǎn)中使用​​80​​。
  人們似乎一致認(rèn)為,如果你的項(xiàng)目是一臺(tái)計(jì)算機(jī)上運(yùn)行的小網(wǎng)站,那么 docker-compose 在生產(chǎn)中不會(huì)有問(wèn)題。
  有個(gè)人建議說(shuō),如果愿意在生產(chǎn)環(huán)境搭建復(fù)雜那么一丟丟,Docker Swarm 就或許會(huì)是更好的選擇,不過(guò)我還沒(méi)試過(guò)(當(dāng)然,如果要這么說(shuō)的話,干嘛不用 Kubernetes 呢?Docker Compose 的意義就是它超級(jí)簡(jiǎn)單,而 Kubernetes 肯定不簡(jiǎn)單 : ))。
  Docker 似乎還有一個(gè)特性,它能夠 ​​把你用 docker-compose 搭建的環(huán)境,自動(dòng)推送到彈性容器服務(wù)(ESC)上​​,聽(tīng)上去好酷的樣子,但是我還沒(méi)有試過(guò)。
 
  docker-compose 會(huì)有不適用的場(chǎng)景嗎
  我聽(tīng)說(shuō) docker-compose 在以下場(chǎng)景的表現(xiàn)較差:
 
  當(dāng)你有很多微服務(wù)的時(shí)候(還是自己搭建比較好)
  當(dāng)你嘗試從一個(gè)很大的數(shù)據(jù)庫(kù)中導(dǎo)入數(shù)據(jù)時(shí)(就像把幾百 G 的數(shù)據(jù)存到每個(gè)人的筆記本電腦里一樣)
  當(dāng)你在 Mac 電腦上運(yùn)行 Docker 時(shí)。我聽(tīng)說(shuō) Docker 在 macOS 上比在 Linux 上要慢很多(我猜想是因?yàn)樗枰鲱~外的虛擬化)。我沒(méi)有 Mac 電腦,所以我還沒(méi)有碰到這個(gè)問(wèn)題。
  以上就是全部?jī)?nèi)容啦!
  在此之前,我曾花了一整天時(shí)間,嘗試使用 Puppet 來(lái)配置 Vagrant 虛擬機(jī),然后在這個(gè)虛擬機(jī)里配置開(kāi)發(fā)環(huán)境。結(jié)果,我發(fā)現(xiàn)虛擬機(jī)啟動(dòng)起來(lái)實(shí)在是有點(diǎn)慢啊,還有就是,我也不喜歡編寫(xiě) Puppet 配置(哈哈,沒(méi)想到吧)。
 
  幸好,我嘗試了 Docker Compose,它真好簡(jiǎn)單,馬上就可以開(kāi)始工作啦!

(編輯:武林網(wǎng))

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 国产欧美第一页 | 国产中文在线 | 色婷婷综合久久久久中文一区二 | 亚洲欧美成人网 | 国产成人精品国内自产拍免费看 | 国产在线小视频 | 国产精品视频久久久久久 | av免费播放 | 亚洲三级av | 老牛影视av一区二区在线观看 | 久久大陆 | 女女野外嗯啊高潮h百合扶她 | 欧美日本在线观看 | 国产免费久久 | 日韩精品一区二区三区免费观看视频 | 成年免费视频 | 久久久一区二区三区捆绑sm调教 | 亚洲精品美女久久久 | 中文字幕视频在线观看 | 亚洲一区在线日韩在线深爱 | 激情综合色综合久久综合 | 欧美日韩精品免费观看视频 | 人人射人人爱 | 一本色道久久综合狠狠躁篇怎么玩 | 黄色网页大全 | 欧美在线观看禁18 | 亚洲情欲网 | 精品久久久久久久久久久久久久 | 欧美日韩久久久 | 91一级 | 久久99精品视频 | 久久久久综合 | 欧美日韩在线观看视频 | 亚洲视频中文字幕 | 国产一区二区精品久久 | 日本精品视频在线播放 | 国产在线一区二区三区 | 中文字幕观看 | 国产精品视频一区二区三区, | 可以免费观看的av | 亚洲精品成人 |