# Docker with node server & nginx ###### tags: `docker` `node.js` `nginx` `linux` 我發現Docker基本原則是這樣的,就是 **一個container只運行一個服務** **一個container只運行一個服務** **一個container只運行一個服務** (很重要所以說三遍) 所以以前我們可能會把 nginx + node 全部都一起裝在一台VM上, 但現在如果要把它docker化,就變成要開兩個container,一個`nginx`一個`node server`的服務。 而不是直接開一個ububtu(之類的)的container然後把全部東西灌在上面build成一個image。 所以如果要把上述的東西docker化,檔案結構會長成這樣 ``` / (專案根目錄) | -- docker-compose.yml ` -- node | | -- index.js | | -- Dockerfile `-- nginx | | -- nginx.conf | | -- Dockerfile ``` 完整範例可以參考我的 [github](https://github.com/tri613/simple-docker-playground) Docker安裝走這邊:(ubuntu 16.04) https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-16-04 ## 一些名詞簡介 OK,所以到底啥是 `Dockerfile` ? 啥又是 `docker-compose` ? ### Dockerfile > 其實它就是用來 build image 的步驟描述檔。 如果你要建立image檔,有兩種方式: 1. 先下載一個base image (像是ubuntu or centos那種),就像是開一台VM一樣, 然後在你開起來的那個container裡面做平常你會在VM裡面做的事情, 再把這個container的狀態`commit`上去變成一個image檔。 2. 把你所有要做的事情寫成一個 `Dockerfile`,然後直接下指令build就好!! 我覺得寫 Dockerfile 的好處是,你不用真的把你的image推到像是docker hub的地方, 而是直接給別人你的 Dockerfile + 需要的源碼讓人家去build就好 感覺這樣進版本庫也比較輕量(?) ### docker-compose 一開始提到了,Docker的基本原則是,**一個container只負責一項服務** 但基本上不太可能一個APP只用到一個服務 (像是本文就用到了 node + nginx) 所以需要 `docker-compose` 來一次幫你把你的 **APP** (服務群?) 開好 (不然也是可以自己先把所有的image build好再一個個開起來啦只是會開到起笑) 那怎麼知道要開哪些服務哩? 這時候就需要用到 `docker-compose.yml` 這個設定檔了 而這個設定檔怎麼寫,下面會有範例所以這邊不多說了 所以兩者關係是這樣的: > 一個 `Dockerfile` 可以build成一個 `image`, 一個 `container` 則是一個 `image` 的實體, 而 `docker-compose.yml` 就是描述很多個 `container` (or service) 之間的交互作用。(吧) 好像沒有很總結到的感覺XDDDD,直接往下看程式比較快(ㄜ) ## node ### index.js (毫無反應,就只是個node server) 陽春到極致的簡單範例: ```javascript= const http = require('http') const port = process.env.PORT || 8080 const requestHandler = function handler(req, res) { res.end("Hello! This is a simple node server!") } const server = http.createServer(requestHandler) server.listen(port, () => console.log(`Node simple server is now listening on *:${port}`)) ``` ### Dockerfile - building from ubuntu ```dockerfile= FROM ubuntu:trusty # install curl & node RUN apt-get update && \ apt-get -y install curl && \ curl -sL https://deb.nodesource.com/setup_7.x | bash - && \ apt-get install -y nodejs WORKDIR /src ADD . /src EXPOSE 8080 CMD ["node", "/src/index.js"] ``` - building from node (with pm2) 直接用官方的node image環境當底, 這個方法build起來速度快很多XD ```dockerfile= FROM node:7.10.1 RUN npm install pm2 -g WORKDIR /src COPY . /src EXPOSE 8080 CMD ["pm2-docker", "process.yml"] ``` - process.yml 這個是 pm2 在用的啦,順便列一下 ```yaml= apps: - script : './index.js' name : 'node-server' exec_mode: 'cluster' instances: 4 ``` `EXPOSE` 好像只是讓大家知道 **container** 打算要使用哪個port, 真正要運行的時候,還是需要加上類似`-p xxxx:8080`這樣的東西。 但因為我們不會直接build images出來,而是透過 `docker-compose` 來建立整套服務, 所以到時候寫在 `docker-compose.yml`裡面就可以了。 #### 手動 build image 並啟動 假如沒有要透過 `docker-compose` 而只是想要啟用單一服務的話, 也可以先手動建立image然後啟動。 `Dockerfile` 就是拿來build image用的, 所以我們現在其實已經擁有所有需要的素材了。 先切到 `node` 本身的目錄下面: ``` $ cd your-project/node ``` 建立image: ``` $ docker build -t your-namespace/node . ``` build完以後執行啟動 ``` $ docker run -d -p 3000:8080 your-namespace/node ``` 連到 `*:3000` 就可以看到我們的node伺服器正常運作中拉,Hooray! ## nginx ### nginx.conf 這 nginx 的 config 也是直接複製網路上範例,(所以我沒有深究它在幹嘛XD) 注意連到 node server 的服務的時候用的是 `http://nodejs:8080` 其中 `nodejs` 是寫在 `docker-compose.yml`裡面 node server的 `name` port 則是當初在 node Dockerfile 裡面`EXPOSE`指定的 port ```config= worker_processes 4; events { worker_connections 1024; } http { server { listen 80; location / { proxy_pass http://nodejs:8080; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } } } ``` #### nginx config 參數配置參考 - http://www.ha97.com/5194.html ### Dockerfile ```dockerfile= FROM nginx COPY nginx.conf /etc/nginx/nginx.conf ``` ## docker-compose ### docker-compose.yml 首先在根目綠下面加上 `docker-compose.yml` 這個檔案 它主要就是來告訴 `docker-compose` 說要開哪些服務 然後這些服務彼此之間的關係等等 ```yaml= nginx: build: ./nginx links: - nodejs:nodejs ports: - "80:80" nodejs: build: ./node ports: - "8080" # 對外沒有port!!!!! 所以外面的人是無法直接連到 node 服務的 ``` ### 啟動 在專案根目錄下面執行: ``` $ docker-compose up -d ``` 注意 `docker-compose` 是要另外裝的,所以沒有要記得裝。 詳細安裝教學:(ubuntu 16.04) https://www.digitalocean.com/community/tutorials/how-to-install-docker-compose-on-ubuntu-16-04 然後就好啦!!! ### 更新 假如更新程式的話怎麼辦????? 像是我的 `node` 裡面的程式碼如果更新了要怎麼辦??? 因為我這邊用的是 `COPY`,所以基本上程式碼算是和docker分開管理(的吧) 我現在的想像是整個project都進版本庫管理 然後在專案底下執行 `git pull` or `svn up` 之類的完畢後,使用 ``` $ docker-compose up --build -d ``` 來建立新版本並更新。 (而且我發現這可以在已經執行中的狀態下使用,可以無痛更新ㄚ!!!!!) 注意 `--build` 這個參數,如果沒有用的話他就會使用已經建立過的版本下去跑, 這樣你更新的程式碼就完全沒用了~ 其他很多像是 `ADD` 跟 `COPY` 差在哪啦,什麼樣的更新方式比較OK啦 這類的細節和討論我不是很清楚, 總之先可以跑起來就好了XD (欸) ## 參考資料 - http://anandmanisankar.com/posts/docker-container-nginx-node-redis-example/ - http://schempy.com/2015/08/25/docker_nginx_nodejs/
×
Sign in
Email
Password
Forgot password
or
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.