Dockerfile 實戰
未使用過請先看 Docker 簡介、指令速查 & 基本操作。
在 Docker hub 可看到幾種 Repository,official(官方)、public(公開)、automated build(自動建立)。
可以指定任何一種當底,在做 layer 堆疊出個人的版本。layer 上限 127 層(v0.7.2)
堆疊個人的 image 有兩種方式,一個是進去 container 中手動安裝,另一種就是 寫 Dockerfile。
本篇不使用 docker-compose 串連獨立 service,而是將所有 service 安裝在同一個容器中(Fat container)。
Dockerfile 結構大致上就是基於某個版本,設定環境參數、使用指定身份、下指令、串資料源、開放PORT、執行容器時對應的動作
開發流程使用 git做版控,並讓 docker hub 連結,有異動時會觸發 auto build
練習流程:
狀況
在 Docker hub 可看到幾種 Repository,official(官方)、public(公開)、automated build(自動建立)。
可以指定任何一種當底,在做 layer 堆疊出個人的版本。layer 上限 127 層(v0.7.2)
堆疊個人的 image 有兩種方式,一個是進去 container 中手動安裝,另一種就是 寫 Dockerfile。
本篇不使用 docker-compose 串連獨立 service,而是將所有 service 安裝在同一個容器中(Fat container)。
Dockerfile 結構大致上就是基於某個版本,設定環境參數、使用指定身份、下指令、串資料源、開放PORT、執行容器時對應的動作
開發流程使用 git做版控,並讓 docker hub 連結,有異動時會觸發 auto build
練習流程:
- ubuntu + nginx
- install
- service auto start
- copy config
- volume
- volume container
- push image
- push dockerfile
- + php7
- + mysql 5.7
- + nodejs7
基本指令
- FROM 底為某個 repository(官方、公開皆可)
- FROM ubuntu
- FROM ubuntu:14.04
- FROM someone/lemp:1.0
- MAINTAINER 維護者
- MAINTAINER wild <[email protected]>
- ENV 環境變數
- ENV NAME=abc
- RUN 下指令,並增加 layer 一層
- RUN <command> 如:RUN apt-get install xxx
- RUN ["executable", "param1", "param2"] 如:
- EXPOSE 要開放的連接阜
- EXPOSE 80 443 8080
- USER 切換使用者(預設為 root)
- USER root
- ONBUILD
- ADD
- COPY 複製檔案到容器中
- COPY /path/src /etc/nginx
- 要異動,必須重 build
- WORKDIR 預設工作路徑
- ENTRYPOINT 執行指令
- CMD 執行指令
- CMD
- ARG
- LABEL
- VOLUME 建立掛載點,允許外部關聯
- VOLUME ["/etc/nginx", "/etc/php",...]
- VOLUME /var/log /var/db
- STOPSIGNAL
Ubuntu + Nginx
- 建一個測試資料夾、script file
$ mkdir lemp
$ cd lemp
$ vi Dockerfile
- 純安裝的 script 內容
FROM ubuntu:14.04
MAINTAINER wild0522 <[email protected]>
USER root
#解決 locale 指令,LANG,LANGUAGE,LC_ALL 為空的狀況
RUN locale-gen en_US.UTF-8
ENV LANG=en_US.UTF-8
ENV LANGUAGE=en_US.UTF-8
ENV LC_ALL=en_US.UTF-8
ENV LC_CTYPE=UTF-8
#解決 TERM is not set 況
ENV TERM xterm
RUN apt-get update
#解決 policy-rc.d denied execution of start 狀況
RUN sed -i "s/^exit 101$/exit 0/" /usr/sbin/policy-rc.d
#使用非互動模式,都用預設值跑過,且全部選 y
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --force-yes nginx
EXPOSE 80
- build、run,檢查 nginx 狀態
$ :wq! #存檔並離開
$ docker build -t="你的暱稱/專案名稱:1.0" .
$ docker images #查看是否有建立成功
$ docker run -tid -p 80:80 --name="lemp_t" 你的暱稱/專案名稱:1.0 /bin/bash
$ docker ps -a #查看 lemp_t 容器是否在執行中
$ docker attach lemp_t #進入 container
root$ service nginx status #顯示 nginx 狀態,此時應該為 not running
root$ exit
$ docker ps -a #lemp_t 容器應該已經停止
$ docker rm lemp_t #刪除容器
- 讓 nginx 能在 run container 後啟動
- (x) RUN update-rc.d nginx defaults
- (x) RUN service nginx restart
- (x) CMD service nginx restart
- (o) ENTRYPOINT service nginx start && /bin/bash
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --force-yes nginx
ENTRYPOINT service nginx start && /bin/bash
EXPOSE 80
$ :wq! #存檔並離開
$ docker build -t="你的暱稱/專案名稱:1.1"
$ docker run -tid -p 80:80 --name="lemp_t" 你的暱稱/專案名稱:1.1 /bin/bash
$ docker attach lemp_t #進入 container
root$ service nginx status #顯示 nginx 狀態,此時應該為 running
root$ ls /etc/nginx/sites-enabled/ #應該只有 default 一個檔案
root$ ctrl + p, 放開後接著 ctrl + q #detach容器
$ docker ps -a #此時 lemp_t 容器仍舊執行中
$ docker stop lemp_t; docker rm lemp_t
- 用 COPY 把外部檔案送進去
- 這種方式,只有在 run 的當下才會複製檔案,若外部檔案異動,就須 stop/rm 並重新 run 一次
$ mkdir sites
$ cd sites
$ vi my_web.conf
$ wq!
$ cd ..
$ vi Dockerfile
ENV TERM xterm
COPY sites/*.conf /etc/nginx/sites-enabled/
RUN apt-get update
$ wq!
$ #build 1.2版,並執行
$ docker attach lemp_t
root$ ls /etc/nginx/sites-enabled/ #變成 2 個檔案
root$ exit
- 用 volume 關聯內外資料夾
- 容器內的資料夾 mount 外面的 folder,可動態變更資料
$ vi Dockerfile
#COPY sites/*.conf /etc/nginx/sites-enabled/ #刪除 COPY
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --force-yes nginx
VOLUME ["/etc/nginx/sites-enabled"]
ENTRYPOINT service nginx start && /bin/bash
$ wq!
$ #build 1.3版
$ docker run -tid -p 80:80 --name="lemp_t" -v /本地端完整路徑/sites:
/etc/nginx/sites-enabled 你的暱稱/專案名稱:1.3 /bin/bash
$ docker attach lemp_t
root$ ls /etc/nginx/sites-enabled/ #變成只有 my_web.conf
root$ ctrl p, q
$ vi sites/my_sec_web.conf
$ wq!
$ docker attach lemp_t
root$ ls /etc/nginx/sites-enabled/ #此時變成 2 個檔案
root$ exit
- 改用 volume container
push image
- 註冊 docker hub
- push
$ docker login #username不是email
$ docker push 暱稱/專案名稱:1.3
- push 結果
- docker hub -> dashboard 應該會多出一個 public Repository
push Dockerfile
- 此方式在 docker Hub 上才 build image,傳輸超快
- 讓 Automated build 服務,取得 github 授權
- docker hub 網站 -> create Automated Build -> Public and Private -> login github -> authorize
- 建立 git repo
- 註冊/登入 github
- New repository 專案命名為 hello -> create_repository
- 複製 repository 網址,ex. https://github.com/帳號/hello.git
- 回到 Dockerfile 資料夾
$ git init
$ git remote add origin https://github.com/帳號/hello.git
$ git config --global user.email "信箱網址" #第一次用 git 才需設定
$ git config --global user.name "暱稱" #第一次用 git 才需設定
$ git add Dockerfile
$ git commit -m "first commit"
$ git push -u origin master
- 建立 docker repo
- docker hub 網站 -> create Automated Build -> github -> 選擇專案名稱 -> create
- 觸發 build
- 未 build 之前,Dockerfile 頁面內容會是空的 or 上個版本
- 當 git push remote 之後,Build Detail 可看 build 過程,點進去可看 Build 過程
- 手動觸發:Dashboard -> hello -> Build Settings -> Branch Master 後方 Trigger 按鈕
- 修改一版 Dockerfile
- 推上去後,就會自動 build
$ git add Dockerfile
$ git commit -m "sec commit"
$ git push
+PHP7
$ vi Dockerfile
RUN DEBIAN_FRONTEND=noninteractive apt-get ... nginx
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --force-yes software-properties-common && LC_ALL=C.UTF-8 DEBIAN_FRONTEND=
noninteractive add-apt-repository ppa:ondrej/php &&
DEBIAN_FRONTEND=noninteractive apt-get update &&
DEBIAN_FRONTEND=noninteractive apt-get install -y --force-yes php7.0 php7.0-fpm php7.0-mysql php7.0-curl php7.0-gd php7.0-json php7.0-mcrypt php7.0-opcache php7.0-xml php7.0-mbstring
VOLUME ["/etc/nginx/sites-enabled","/var/www","/var/log"]
ENTRYPOINT service nginx start && service php7.0-fpm start && /bin/bash
$ wq!
$ #build 1.4版
$ docker run -tid -p 80:80 --name="lemp_t" -v /本地端完整路徑/sites:/etc/nginx/sites-enabled -v /本地端完整路徑/www:/var/www -v /本地端完整路徑/log:/var/log 你的暱稱/專案名稱:1.4 /bin/bash
$ ls #應該可以看到多了 www、log 兩個資料夾
$ docker attach lamp_t
$ service nginx status #nginx 掛了?
$ nginx -t #原因是 log 建立失敗
- log
+ mysql 5.7
$ vi Dockerfile
RUN ... install php
RUN LC_ALL=C.UTF-8 DEBIAN_FRONTEND=noninteractive add-apt-repository -y ppa:ondrej/mysql-5.7 && apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --force-yes mysql-server;
ENTRYPOINT service nginx start && service php7.0-fpm start && service mysql restart && /bin/bash
$ wq!
$ #build 1.4 版,run
$ docker attach lemp_t
root$ mysql -V
+ Nodejs 7.x
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --force-yes curl && \
curl -sL https://deb.nodesource.com/setup_7.x | sudo -E bash - && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --force-yes nodejs
狀況
- locale: Cannot set LC_XXXX to default locale: No such file or directory
- 指定 ENV 語系之前,加上 RUN locale-gen en_US.UTF-8
- debconf: (TERM is not set, so the dialog frontend is not usable.)
- 加上 ENV TERM xterm
- dpkg-preconfigure: unable to re-open stdin: No such file or directory
- (o) 安裝前才賦予
- RUN DEBIAN_FRONTEND=noninteractive apt-get install -y xxxxx
- 必須接在 install 前
- (x) 直接加環境變數
- ENV DEBIAN_FRONTEND=noninteractive
- 此方式將會在 container 中持續生效
- noninteractive 非互動式(非交互式)
- 就是不要求用戶輸入,直接用 default 值跑完全程
- invoke-rc.d: policy-rc.d denied execution of start.
- 加上 RUN sed -i "s/^exit 101$/exit 0/" /usr/sbin/policy-rc.d
- 似乎會導致 mongoDB 安裝失敗
- connect() to unix:/var/run/php/php7.0-fpm.sock failed (111: Connection refused)
- 連不到 php7.0-fpm,用 service php7.0-fpm status 檢查狀態並處置
- mysql 5.7 外部無法連入
- 將 bind-address = 127.0.0.1 改成 0.0.0.0
- 舊版可能在 /etc/mysql/my.cnf,新版在 /etc/mysql/mysql.conf.d/mysqld.cnf 內
- 當然,mysql user 權限要開放 %
- apt does not have a stable CLI interface. Use with caution in scripts.
- debconf: delaying package configuration, since apt-utils is not installed
- W: --force-yes is deprecated, use one of the options starting with --allow instead.
- /bin/sh: 1: locale-gen: not found
- 前面加上 RUN apt-get clean && apt-get update && apt-get install -y locales
- WARNING: apt does not have a stable CLI interface. Use with caution in scripts.
- Docker and PID 1 zombie 相關文獻
- 狀況:一個 proccess 被 kill 之後,雖然 memory 已經釋放,但仍佔用 kernel 資源,直到 proccess 全滿,無法在 build 新的 proccess
- ubuntu 可改用 phusion/baseimage
Dockerfile 實戰
Reviewed by Wild
on
12/29/2016 06:26:00 下午
Rating:
沒有留言:
沒有Google帳號也可發表意見唷!