歡迎光臨
每天分享高質量文章

使用Docker高效搭建開發環境

Docker作為輕量級的基於容器的解決方案,它對系統侵入性低,容易移植,天生就適合做複雜業務部署和開發環境搭建,今天給大家帶來的是奇虎360的開發是如何使用Docker高效搭建開發環境的。
作為一個平時喜歡折騰的開發人員,我喜歡嘗試各種環境,使用感興趣的各種開源軟體。
同時,我也是有一些相對的小潔癖,很喜歡Linux中權限最小化原則,我也不喜歡自己的環境中有太多不知道的東西。
做了多年的Web開發,我接觸到的環境大致如下:
  1. 操作系統從CentOS 5到CentOS 7;

  2. Web Server從Apache到Nginx;

  3. 開發語言從最初的PHP 5.2到PHP 7,又到現在主要使用Go,馬上還會開始接觸C++;

  4. 資料庫從MySQL 5.1到現在的5.7,前陣子又開始折騰MariaDB;

  5. Cache選型從Memcache到Redis;

  6. 佇列用過Kafka,去年開始大量使用NSQ。

公司雖然有專門負責部署、運維這些服務的同學,但我在開發的時候,還是喜歡自己來搭建這些東西,因為這樣通常可以對使用到的服務有更多的認識,也能幫助自己使用的更好。
今天我就來和大家分享下我是如何高效的搭建好自己的開發環境的。

搭建前說明

這裡先說明一點,對每個開源軟體,我幾乎都是自己編譯部署的,而不會使用類似yum install這種方式,也很少直接下載官方編譯好的二進制包,這都是為了能多深入瞭解用到的開源軟體。
但一些依賴的動態庫檔案,如zlib等,還有編譯工具,如GCC、make等,我都是通過方便的yum install這種方式直接安裝的,否則會累死。

傳統做法

我在很長的一段時間內,都是把每個軟體的編譯、安裝過程寫成一個腳本,之後再需要用的時候直接運行腳本即可,但這樣的方式,通常會遇到下麵這些問題:
  1. 腳本只能在我當時的操作系統環境下運行。記得當時購買過不同服務商的VPS,雖然不同VPS我都使用同樣的Linux發行版,但腳本通常都不能一鍵跑完。這也是沒辦法,因為每個VPS服務商都會製作自己的操作系統鏡像版本。

  2. 操作系統升級,如CentOS 5 – 6,或是換為Ubuntu,這樣基本上腳本都跑不了。

  3. 軟體升級,如MySQL 5.2 – 5.6,構建工具改為CMake,依賴庫改變或升級。

  4. 如果某個軟體依賴的公共庫版本和其它軟體不同,且公共庫升級後和舊版不兼容,那你就只能為這個軟體單獨編譯公共庫了,如果只是普通的公共庫還好,但如果是所需要的編譯工具版本不同,那可就慘了。

上面這些問題,如果你想每個發行版維護一個腳本,那會累死,因為一旦你每次想升級一個軟體,難道每個發行版都要編譯一遍嗎?這就變成了收穫價值很低的體力勞動了。
由於喜歡折騰的個性,我對操作系統的升級以及軟體包版本的升級又經常發生,所以一直以來,我都在尋找一個好方法,能很方便的維護好自己的開發環境,儘量做到只=新東西只為它工作一次,最後我找到了Docker,目前我都是用它來搭建自己的開發環境的。

Docker做法

先概括介紹下我的方法:
  1. 讓每個軟體運行在容器中,因為運行的容器環境是可以固定下來的,所以編譯安裝腳本寫一個就可以了。

  2. 代碼使用資料捲的方式加載到需要的容器中。

  3. 因為是開發環境,所以網絡方面使用最簡單的–net=host。

  4. 將鏡像的創建、容器的啟動維護在Git專案中,並抽象出統一的構建過程,很方面的做到新軟體接入,新機器部署。

下麵用實體來說明把:
示例Nginx環境構建
我將構建過程放到Git中:https://gitee.com/andals/docker-nginx。
Readme中記錄了構建所需要執行的腳本命令,大家訪問上面的網址就可以看到,這裡我簡單介紹下專案的結構:
├── Dockerfile        //創建鏡像的Dockerfile
├── pkg               //編譯好的二進制包,可以直接使用,此外軟體運行的一些配置檔案或第三方包也放在這裡
│   ├── conf
│   │   ├── fastcgi.conf
│   │   ├── http.d
│   │   ├── include
│   │   ├── koi-utf
│   │   ├── koi-win
│   │   ├── logrotate.conf
│   │   ├── logrotate.d
│   │   ├── mime.types
│   │   ├── Nginx.conf
│   │   ├── scgi_params
│   │   ├── uwsgi_params
│   │   └── win-utf
│   ├── luajit-2.0.3.tar.gz
│   └── Nginx-1.8.1.tar.gz
├── README.md
├── script                //裡面放構建腳本
│   ├── build_image.sh    //構建鏡像使用
│   ├── build_pkg.sh      //編譯軟體包時使用
│   ├── init.sh           //容器啟動時執行
│   └── pre_build.sh      //軟體依賴的共享庫,編譯和構建時都會用到
└── src                   //編譯時需要的軟體原始碼
   ├── modules
   │   ├── ngx_devel_kit-0.2.19.tgz
   │   ├── ngx_echo-0.53.tgz
   │   └── ngx_lua-0.9.7.tgz
   ├── Nginx-1.8.1.tar.gz
   └── openssl-1.0.2h.tar.gz
DockerFile說明
Dockerfile結構如下:
FROM andals/CentOS:7
MAINTAINER ligang
LABEL name="Nginx Image"
LABEL vendor="Andals"
COPY pkg/ /build/pkg/
COPY script/ /build/script/
RUN /build/script/build_image.sh
CMD /build/script/init.sh
整個構建框架為:
  1. 把構建需要的包(PKG目錄中)放到鏡像中

  2. 把構建腳本放到鏡像中

  3. 執行構建腳本

  4. 容器啟動時,執行init.sh,裡面啟動相應的服務

Readme.md中記錄了執行構建的命令和容器運行命令,示例運行如下:
[email protected] ~/devspace/dbuild $ git clone [email protected]:andals/docker-Nginx.git Nginx
Cloning into 'Nginx'...
......
[email protected] ~/devspace/dbuild $ cd Nginx/
[email protected] ~/devspace/dbuild/Nginx $ ngxVer=1.8.1
[email protected] ~/devspace/dbuild/Nginx $ docker build -t andals/Nginx:${ngxVer} ./
Sending build context to Docker daemon   30.7MB
Step 1/8 : FROM andals/CentOS:7
......
Successfully built ea8147743031
Successfully tagged andals/Nginx:1.8.1
[email protected] ~/devspace/dbuild/Nginx $ docker run -d --name=Nginx-${ngxVer} --volumes-from=data-home -v /data/Nginx:/data/Nginx --net=host andals/Nginx:${ngxVer}
dbf3c0617eb34c4b1b4ea54c2961989612d5474db3b1acd1d717221e6e5cb516
說明:
–volumes-from=data-home這個就是我放置代碼的資料捲,我喜歡把代碼放到$HOME下麵,所以這個捲的相關信息如下:
[email protected] ~ $ docker ps -a
CONTAINER ID        IMAGE                    COMMAND                  CREATED             STATUS                   PORTS               NAMES
578912a08ea7        andals/CentOS:7          "echo Data Volumn Ho…"   9 days ago          Exited (0) 9 days ago                        data-home
......
[email protected] ~ $ docker inspect 578912a08ea7
......
       "Mounts": [
           {
               "Type": "bind",
               "Source": "/home",
               "Destination": "/home",
               "Mode": "",
               "RW": true,
               "Propagation": "rprivate"
           }
......
/data/Nginx中放置Nginx的conf、log等,每個軟體運行時的conf、log、data等我都統一放置在/data下麵,如:
[email protected] ~ $ tree -d /data/ -L 1
/data/
├── mariadb
├── Nginx
└── redis
[email protected] ~ $ tree -d /data/Nginx/
/data/Nginx/
├── conf
│   ├── http.d
│   ├── include
│   └── logrotate.d
└── logs
啟動容器時使用–net=host,作為開發環境簡單實用。
我就是通過這種方法完成了開發環境的構建,不再有多餘的重覆工作,並且新機器部署開發環境效率極高。
我目前用到的容器環境如下:
ligang@vm-xUbuntu16 ~ $ docker ps -a
CONTAINER ID        IMAGE                    COMMAND                  CREATED             STATUS                   PORTS               NAMES
dbf3c0617eb3        andals/Nginx:1.8.1       "/bin/sh -c /build/s…"   33 minutes ago      Up 33 minutes                                Nginx-1.8.1
3e31ef433298        andals/php:7.1.9         "/bin/sh -c /build/s…"   8 hours ago         Up 8 hours                                   php-7.1.9
360f94bf9c43        andals/jekyll:latest     "/bin/sh -c /build/s…"   9 days ago          Up 10 hours                                  jekyll-latest
0a7d58d1ca5e        andals/redis:4.0.8       "/bin/sh -c /build/s…"   9 days ago          Up 10 hours                                  redis-4.0.8
fdaa655b4a11        andals/samba:4.4.16      "/bin/sh -c /build/s…"   9 days ago          Up 10 hours                                  samba-4.4.16
6ad00a69befd        andals/mariadb:10.2.14   "/bin/sh -c /build/s…"   9 days ago          Up 10 hours                                  mariadb-10.2.14
578912a08ea7        andals/CentOS:7          "echo Data Volumn Ho…"   9 days ago          Exited (0) 9 days ago                        data-home
輔助工具dockerbox
使用Docker環境後,有個問題,就是沒有辦法很方便的和軟體交互。
這是因為軟體都執行在容器中,比如重啟Nginx吧,需要下麵這幾步:
  1. 找到Nginx這個容器

  2. 進入Nginx這個容器

  3. 在容器裡面再執行reload

也可以是:
  1. 找到Nginx這個容器

  2. 使用docker exec

但無論哪種方式,都比原先直接執行命令麻煩的多。
另外,有時也需要進入容器中,查看服務的運行情況。
為了方便的做這些事情,我開發了一個工具dockerbox,可以很方便的做到這些事情。
dockerbox的詳情及使用方法請見:https://github.com/ligang1109/dockerbox
配置開機運行
最後再說下如何配置開機啟動。
我使用虛擬機搭建的開發環境,所以配置這個會省事好多,我使用用了systemd:
[email protected] ~ $ ll /lib/systemd/system/dstart.service
-rw-r--r-- 1 root root 229 4月   3 21:35 /lib/systemd/system/dstart.service
[email protected] ~ $ cat /lib/systemd/system/dstart.service
[Unit]
Description=Docker Container Starter
After=network.target docker.service
Requires=docker.service
[Service]
ExecStart=/usr/local/bin/dbox -dconfPath=/home/ligang/.dconf.json start all
[Install]
WantedBy=multi-user.target
dbox請參考dockerbox的使用方法。

結束語

上面說的是我現在使用的開發環境搭建方法,有興趣愛折騰的同學不妨試試看,如果你有更好的方法,也希望能分享給我。
本文轉載自公眾號:HULK一線技術雜談,點擊查看原文

Kubernetes入門與進階實戰培訓

本次培訓內容包括:Docker基礎、容器技術、Docker鏡像、資料共享與持久化、Docker三駕馬車、Docker實踐、Kubernetes基礎、Pod基礎與進階、常用物件操作、服務發現、Helm、Kubernetes核心組件原理分析、Kubernetes服務質量保證、調度詳解與應用場景、網絡、基於Kubernetes的CI/CD、基於Kubernetes的配置管理等,點擊瞭解具體培訓內容

5月11日正式上課,點擊閱讀原文鏈接即可報名。
赞(0)

分享創造快樂