分類: General

  • 架設 Docker Registry v2

    我的架設方式與官方文件不太一樣,所以踩了不少雷。

    官方文件傾向把 nginx 與 docker-registry 都用 Docker container 的方式連接 (link) 部署,而我的方式與層次是:

    1. AWS ELB
    2. Nginx on EC2 Host OS
    3. Dockerized  docker-registry (registry:2)

    因為我想要閃掉 SSL/TLS 的設定,還有惱人的 private key passphrase,所以讓現成已經掛好了憑證的 ELB 充當 SSL/TLS termination proxy。在 ELB 後面的 nginx 與 docker-registry 就不用煩惱憑證的設定問題。

    Nginx 主要是負責提供 HTTP basic access authentication,在 docker-registry 前提供一層帳密安全關卡,由於我個人實在是很討厭使用 link,所以把它放在 host 裡。設定檔大致如下:

    server {
      listen 8080;
      server_name docker.registry.in.my.com;
      client_max_body_size 0;
      chunked_transfer_encoding on;
    
      access_log    /var/log/nginx/docker-registry-access.log;
      error_log     /var/log/nginx/docker-registry-error.log;
    
      location / {
        # Do not allow connections from docker 1.5 and earlier
        # docker pre-1.6.0 did not properly set the user agent on ping, catch "Go *" user agents
        if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))|Go ).*\$" ) {
          return 404;
        }
    
        # To add basic authentication to v2 use auth_basic setting plus add_header
        auth_basic "registry.localhost";
        auth_basic_user_file /etc/nginx/conf.d/registry.password;
        add_header Docker-Distribution-Api-Version  registry/2.0    always;
    
        proxy_pass                          http://127.0.0.1:5000;
        proxy_set_header  Host              $http_host;
        proxy_set_header  X-Real-IP         $remote_addr;
        proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header  X-Forwarded-Proto https;
        proxy_set_header  X-Original-URI    $request_uri;
        proxy_set_header  Docker-Distribution-Api-Version   registry/2.0;
        proxy_read_timeout                  900;
      }
    }

    過程中我遇到的幾個大地雷有:

    • Ubuntu 14.04 內的 nginx 版本太舊,不支援 add_header 的 always 指令,導致不會送出該識別 header,所以 docker login 會判斷這個 docker-registry 為 Invalid registry endpoint,解決方法就是要從 nginx 官網裝新版(至少 1.7.5 以上,這顆地雷是從 [Running Secured Docker Registry 2.0 – Container Solutions] 這篇看到提示才解掉的)。
    • 由於 nginx <-> docker-registry 之間通訊是走 http://,所以在 push image 的時候,一開始從 remote 下 PUT 指令還是 https://,但是接著 docker-registry 會根據 X-Forwarded-Proto 的值送出 Location: http://xxx HTTP header 請 client 轉址,導致接下來的 PUT 操作失敗,解決方法就是要把 X-Forwarded-Proto 強制指定為 https

    幾個經驗:

    • 善用 curl -v 給的資訊來判斷,不要瞎猜。
    • V2 目前還是很多坑,使得你不得不去看 source code,但是還好小的我還學過一點 Go
  • OpsWorks + Docker 管理架構

    今(昨?)天在公司跟同仁分享的經驗,簡單筆記一下:

    • Elastic Beanstalk 自訂的彈性與便利性,都比不上 OpsWorks。
    • 公司在 Web 的主要使用語言是 Ruby:
      • OpsWorks = AWS + Chef
      • Chef 是用 Ruby 來管理 infrastructure
      • 所以相對來說,入門門檻相對較低
      • 理想上,應該可以跟 Vagrant 用同一套 Chef Cookbook(s),達成跨方案快速部署開發與營運環境
    • OpsWorks 每個 Stack 內只允許有一個 Rails App layer
      • 如果覺得在 custom layer 照抄 AWS 的 Rails App layer 套用的 recipes,就可以解決這個限制,你就會踩雷踩到想哭。
      • 如果為了要使用內建的 Rails App layer 而拆分到不同 stacks,又顯得太蠢,且無法佔到「放在同一個 stack 時可共用很多管理資料」的便宜。
    • 目前(我)已知最好的方法,就是架 Docker
      • 利用 Docker 的隔間特性,以 KTV 包廂為例,理想上 (container) A 房間開趴,不會影響到 (container) B 房間,更不會影響到大廳 (host)。
      • 所以我們甚至可以一台 EC2 instance 裡部署 A 應用,如果資源有餘裕,就可以堆 B 應用、C 應用、D 應用…而不互相打架,且不會被 OpsWorks 一堆未知的地雷炸到。
      • 實務上我會這樣堆疊:debian:stable → rvm-ruby-base → rails-base → app-base → app。
      • rvm-ruby-base 就是先在裡頭裝好 RVM 以及 Ruby。
      • rails-base 是預先裝 Rails 會用到的 Debian packages 如 NodeJS (XD)
      • app-base 預先 git clone 把 application 的 code 拉下來,先跑 bundle install,這樣預先裝好一堆落落長的 gems 後,往後疊 app 上去就不用把時間耗在重新安裝。
      • app 則是做 git pull,把異動拉下來後認 branch/tag 部署。這個放在 deploy 類的 recipes 底下,上面那些則是擺在 setup 類底下。
    • 好處:
      • 我們基於 Rails 的產品很多,用 AWS 也用很大,所以每個產品理想上都可以用同一套 cookbook(s) 做部署基礎,只需在 deploy 這邊自訂個別需求就好。
      • 就算不用 Rails,還是可以在 rvm-ruby-base 上疊其他的 Ruby 應用。
      • 好,就算不用 Ruby,你還是可以在 debian:stable 上堆其他應用。
      • 因為用了 OpsWorks & Chef,我們可以用 template 動態產生 Dockerfile 以及設定檔,可以當成「超彈性隨你玩加強版 ECS (EC2 Container Service)」來用。
    • 先決條件:
      • 規劃良好的 VPC subnets, security groups
      • 看 AWS 官方的 cookbooks 怎麼寫,模仿,並瞭解 node 物件有哪些東西可以方便我們部署
      • 考量日後發展,彈性劃分 Docker 堆疊
  • 編譯 B2G (Firefox OS)

    其實之前幫 ZTE Open (inari) 編過,這次是重新拉過一次 source code 下來,然後先試著編譯 emulator 確認基本可動。

    我是把 source code 放在外接硬碟上 (/run/media/yhh/500G/),因為筆電內的 SSD 已經沒有太多可用空間。

    先拉 source code:

    cd /run/media/yhh/500G/
    sudo git clone git://github.com/mozilla-b2g/B2G.git
    sudo chown -R yhh:users B2G
    

    然後先去編一個編譯過程中需要的 make 3.82:

    sudo tar xvfj make-3.82.tar.bz2
    cd make-3.82
    ./configure --prefix=/run/media/yhh/500G/
    make && sudo make install
    export PATH=/run/media/yhh/500G/bin:$PATH

    接著切換 JDK 版本至 openjdk-7:

    sudo archlinux-java set java-7-openjdk

    開始設定與建置:

    cd /run/media/yhh/500G/B2G
    BRANCH=v2.2 ./config.sh emulator
    ./build.sh -j1

    編譯過程只開一個 job,是因為之前發現若跑多個 jobs 會有前後相依衝突的問題,造成編譯失敗。

    snapshot74 snapshot72

    編出來的 emulator,實際跑起來發現在捲動畫面時,繪圖會不定時黑掉或破圖,不過沒關係,如一開始講的,我只是要確認這份 source code 編出來的東西基本可動而已。回台北後要再實際編一套 2.2 給 ZTE Open 用。

  • Modern Web 2015 Day 2

    首先是 PHP 老爹先簡單講為什麼會有 PHP,再花很多時間在介紹 PHP 7 的新特點,以及在效能上的顯著改善。就語法上來說,很多的語法糖讓 PHP 與時俱進,變得更好用,這也看得出來 PHP 的務實取向。

    我聯想到昨天聽獎金獵人的場次,對於「只會改 Drupal module 的人不能說是會 PHP 的 PHPer」論點,其實一直覺得哪裡怪怪的、說不上來。到現在才想到,其實 Drupal 本身就是一個框架,並圍繞著它的 hook 範式來加掛功能,這就是 Drupal way。如果 Drupal 是用其他語言開發的,很有可能還是會走一樣的 hook 範式。而其他的框架如何去使用 PHP 演化出各自的範式,也是開發者的決定。

    極端一點地說,除非不特地使用某種框架,自己從頭用純 PHP 刻,不然我不覺得換用另一個框架,就比較「會 PHP」了。

    其實我也好久沒寫 Drupal 了,以上都是我的嘴砲,請大家鞭小力一點。

    接下來我聽的場次是 Yahoo! 的,講設計團隊的 U.S.E.R 文化 (User, Space, Experiment, Repeat),主張應該打破傳統大公司的部門編制,採用 task force 方式重新找回「團隊」,並走出辦公室,實際去瞭解、去看用戶、去做 user study。特別讓我覺得該省思的一點是,工程師的思維會以為拍賣網站的最好設計,是讓買家看完賣家的商品描述就秒懂,二話不說直接下標。但是實際上買賣雙方的信任關係是在互動溝通中建立出來的,並不是讓買方一句話都不用說。這就是為什麼他們的拍賣 App 會決定「讓上架變簡單」。

    然後我去聽 Pinkoi 的場次,講行動版網站如何從技術面來提昇 UX。對我而言的重點在於 Rendering Performance 的觀念,要減少頓挫、不連續的現象,就要減少某些很昂貴的消耗。

    Jeremy Lu 講 React Native 的場次就一整個技術宣道大會風格,只要記住 Single Source of Truth, Thinking in Component, Always Redraw (in VDOM) 三原則,加上技術導入門檻極小的 JS,以及原生軟體的 UI/UX/Performance,讓 React & React Native 可能成為 Web 與 native app 開發的苦逼業界救世主。

    松田明的演說對於我這個 Rubyist 來說其實並沒有新東西,而松田さん調查在座有多少 Ruby 用戶時,看來也是不多。我想我自己也是要努力一點,多去用實際的成果證明 Ruby & Rails 是有意思、有搞頭的。

    橋本さん的演說也是很有趣。我之前就試用過 Backlog 了,只是不知道在這軟體變這麼可愛、好用之前,其實有一段因為 UX 不佳、群眾對「工作狀況放在別人家網站管理」有心理障礙的撞牆期,後來透過 UX 的改善才逆轉過來,成為成功的產品。

    最後一場我去聽陳雅博講 UX 的哲學,很受感動與啟發,UX 真的不是一個特定部門、特定人員(如一般人可能以為是 VD)負責的,而應該是整個企業、整個團隊都該有的 sense。且產品若原本就有本質上的問題,也不該期望 UX 可以拯救產品,所謂金玉其外、敗絮其內,最終仍是騙不過用戶的。

    「好的專案流程重要性不低於成果,但若沒有適當的思維及做事心態,流程並不具備任何意義。」

    「正確的思維是教不出來的,是要花時間被培育而出的。」

    演說尾段這兩張投影片上的句子特別讓我有感觸。

  • Modern Web 2015 Day 1

    報到的時候由於不諳動線規劃,所以跟報到櫃台人員發生一點誤會,主要責任還是在我,是我修養不到家。雖然後來跟對方道歉了,但是在這裡還是想要再次跟當事人表示歉意。

    JavaScript 老爸的演講很精彩,回顧與展望了 JS 的發展,只是我印象最深刻的還是 asm.js 的威力展示。(爆)

    接下來雖然我選擇聽蔡學鏞的場次,起初是基於追星的心態,畢竟受他超高水準的譯作獲益不少,且很少人的譯者序可以寫到比作者序還引人入勝的。但是真正聽過他講其個人獨創的 3D 架構方法,就有種「聽過這場就值得這報名費了」的滿足感,這是真正知道如何治學的人,將其心得化為有系統的知識,再用易懂的敘述講給別人知曉。我只能說:「佩服!」

    再來我原本打算要聽拓元的場次,卻臨時改變心意去聽獎金獵人如何逃離 Drupal 的泥淖。很可惜沒聽到他們如何處理原有資料庫,畢竟這才是重點。

    下午第一場聽 KKTIX 的場次,重點就是他們並不是完全拋掉 Ruby on Rails,事實上還持續跟上最新版本。務實地將 Go 與 Rails 各自用在其擅場。

    唐鳳的演說很鼓舞人心,其實這陣子我的情緒很低落,聽過唐鳳的演說,以及接下來 Art Pai 的場次後,有平復一些。

    Mozilla 的場次很有意思,一般做手機的多螢幕是使用多個 user agent 或直接 mirroring,但是在 Firefox OS 上他們做的是單一 user agent 在不同螢幕顯示不同內容。

    最後一場我聽 Paul Li 的場次講 frontend 的 BDD,講者真是太有趣了,滿滿的笑點讓我從頭忍笑到尾,但是演說的內容其實是很紮實的前端測試技術,聽完真的獲益良多。

  • 在 IntelliJ IDEA 與 Eclipse 新增程式語言支援

    繼續昨天的研究…。

    初步看來就是要在平台內實作「近乎整個編譯器」。之前我知道 Eclipse 推的 Xtend 語言,(另)一個號稱「更好的 Java」,是從 Xtext 衍生出來的計畫,但也只是沾沾醬油,未嘗細究 Xtext 是什麼樣的東西。

    雖然我是個非 CS 本科的外行人,但是我對 compiler, assembler 如何產出小時候在 hex editor 與 disassembler 看到的那些機器碼,一直很感興趣,卻始終因為個人的怠惰,也缺乏強烈的動機,沒有認真下去研究。也許這次是個好機會。