├── .gitignore ├── LICENSE ├── README.md ├── Vagrantfile ├── build-chat-onbuild ├── ABOUT-THIS-PATCH.md ├── Dockerfile ├── Dockerfile.official-0.10.36-onbuild ├── README.md ├── index.html ├── index.js └── package.json ├── build-chat ├── .dockerignore ├── ABOUT-THIS-PATCH.md ├── Dockerfile ├── README.md ├── docker-compose.yml ├── index.html ├── index.js └── package.json ├── build-fork ├── .dockerignore ├── Dockerfile ├── docker-compose.yml ├── fork └── getpid ├── build-io ├── Dockerfile ├── README.md └── io.sh ├── build-mcrypt ├── Dockerfile.nodejs ├── Dockerfile.official-5.6.6 ├── Dockerfile.php ├── Dockerfile.php-new ├── README.md ├── centos-nodejs-mcrypt │ ├── README.txt │ ├── Vagrantfile │ └── example.js ├── demo-nodejs ├── demo-php ├── example.js ├── example.php ├── libmcrypt-dev_2.5.8-3.1_amd64.deb ├── libmcrypt-dev_2.5.8-3.3_amd64.deb ├── libmcrypt4_2.5.8-3.1_amd64.deb ├── libmcrypt4_2.5.8-3.3_amd64.deb ├── node_modules │ └── mcrypt │ │ ├── .npmignore │ │ ├── LICENSE │ │ ├── README.md │ │ ├── binding.gyp │ │ ├── build │ │ ├── Makefile │ │ ├── Release │ │ │ ├── .deps │ │ │ │ └── Release │ │ │ │ │ ├── mcrypt.node.d │ │ │ │ │ └── obj.target │ │ │ │ │ ├── mcrypt.node.d │ │ │ │ │ └── mcrypt │ │ │ │ │ └── src │ │ │ │ │ └── mcrypt.o.d │ │ │ ├── linker.lock │ │ │ ├── mcrypt.node │ │ │ └── obj.target │ │ │ │ ├── mcrypt.node │ │ │ │ └── mcrypt │ │ │ │ └── src │ │ │ │ └── mcrypt.o │ │ ├── binding.Makefile │ │ ├── config.gypi │ │ └── mcrypt.target.mk │ │ ├── package.json │ │ ├── src │ │ ├── mcrypt.cc │ │ └── mcrypt.h │ │ ├── test.js │ │ └── test │ │ └── test.js └── package.json ├── build-nginx ├── Dockerfile-daemon-off ├── Dockerfile-daemonize ├── Dockerfile.official-1.9.0 ├── README.md └── docker-compose.yml ├── build-redis-el5 ├── Dockerfile ├── README.md ├── jemalloc-3.6.0-2.el5.x86_64.rpm └── redis-2.8.19-1.el5.remi.x86_64.rpm ├── build-redis-linking ├── Dockerfile ├── Dockerfile.official-2.8.19 ├── README.md ├── benchmark ├── client ├── docker-compose-mixed.yml ├── docker-compose.yml └── redis-server_2.8.19.deb ├── build-redis-mini ├── .dockerignore ├── Dockerfile ├── redis.conf ├── rootfs.tar.gz └── src │ ├── build-rootfs.sh │ ├── clean.sh │ └── redis-3.0.0.tar.gz ├── build-redis ├── Dockerfile ├── Dockerfile.official-2.8.19 ├── README.md └── redis-server_2.8.19.deb ├── build-walk ├── README.md ├── case1 │ ├── Dockerfile │ └── walk-static ├── case2 │ ├── Dockerfile │ └── walk-dynamic ├── case3 │ ├── Dockerfile │ ├── rootfs-from-ubuntu1404.tar.gz │ └── walk-dynamic ├── case4 │ ├── Dockerfile │ ├── rootfs-from-centos511.tar.gz │ └── walk-dynamic ├── case5 │ ├── Dockerfile │ └── walk-dynamic ├── src │ ├── README.md │ ├── c-version │ │ ├── Makefile │ │ └── walk.c │ └── golang-version │ │ ├── Dockerfile-compile │ │ ├── Vagrantfile │ │ ├── build.sh │ │ └── walk.go ├── walk-cases.png ├── walk-dynamic └── walk-static ├── config.md ├── img ├── download-virtualbox.png ├── icon-github-fork.png ├── icon-github-watch.png ├── vbox-diskspace.png └── vbox-win64-error.png ├── intro.md ├── linking-full ├── README.md ├── fig.yml ├── flows.png ├── gen-fluentd-conf.sh └── wrk-script.lua ├── make-registry-box ├── IMAGE-LIST ├── README.md ├── Vagrantfile ├── build.sh └── cleanup.sh ├── prepare.md ├── provision ├── setup-docker-tools.sh ├── setup-env.sh └── setup-hosts.sh ├── reverse-proxy ├── README.md ├── app │ ├── Dockerfile │ ├── index.js │ └── package.json ├── certificate.crt ├── certificate.key ├── certificate.pem ├── docker-compose-2.yml ├── docker-compose.yml ├── haproxy-2.cfg ├── haproxy.cfg ├── make-cert.sh ├── nginx.conf ├── pull-images.sh ├── redis.conf └── reverse-proxy.png ├── setup-vagrant ├── setup-vagrant.bat └── vagrant-tutorial └── Vagrantfile /.gitignore: -------------------------------------------------------------------------------- 1 | .vagrant 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2015 William Yeh 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | docker-workshop 2 | === 3 | 4 | Slides and lab materials for my Docker Workshop (in Traditional Chinese). 5 | 6 | 7 | ## Background 8 | 9 | After given 2 Docker speeches at the end of 2014 (see [A Gentle Introduction to Docker, a “Write Once, Run Anywhere” Containerization Technology](http://jcconf.tw/2014/docker-most-write-once-run-anywhere.html) at JCConf Taiwan 2014 and [Twelve Factor App in Docker](http://containersummit.ithome.com.tw/) at Container Summit 2014), we've seen a growing demand for a systematic, practical, and step-by-step Docker workshop. Therefore, I design this 6-hour workshop materials to fulfill the need. 10 | 11 | 12 | ## Course Introduction 13 | 14 | Read the document ☛ [Docker 建置實戰講堂・課程簡介](intro.md). 15 | 16 | If your organization needs customized training programs and tailored courses, please contact me at william.pjyeh@gmail.com 17 | 18 | 19 | 20 | ## Preparation 21 | 22 | Read the documents: 23 | 24 | - [行前準備 Part 1:申請帳號、安裝軟體](prepare.md) ☚ 愈早進行愈好! 25 | 26 | - [行前準備 Part 2:預載範例程式碼](config.md) ☚ 建議等開課前一週再進行。 27 | 28 | 29 | ## Companion Slides 30 | 31 | View slides online: http://bit.ly/docker-slides 32 | 33 | FYI, the `gh-pages` branch stores the slide files, mostly in markdown format. 34 | 35 | 36 | 37 | ## Course Feedback 38 | 39 | - 「從無到有,對於 Docker 有了基本的認識,也大概知道學習的方向。」 40 | 41 | - 「了解現行 Docker 發展技術及實際操作。」 42 | 43 | - 「建立有系統的 Docker 基礎背景。」 44 | 45 | - 「對 Docker 架構有更進一步瞭解。」 46 | 47 | - 「快速進入 Docker 世界,避免會碰到的地雷。」 48 | 49 | - 「學會 GitHub 與 Docker Hub 連動。」 50 | 51 | - 「了解 Docker 是否適用於 production server 上。」 52 | 53 | - 「希望有進階的實務範例銜接課程。」 54 | 55 | - 「快開進階課吧!」 56 | 57 | 58 | ## History 59 | 60 | **v5.0** / 第五梯次 (2015-06-27) 61 | 62 | - 增加更多實例,示範 container linking 的實務手法。 63 | - 提前以範例介紹初學者常見的兩大地雷:volume 及 network。 64 | 65 | 66 | **v4.0** / 第四梯次 (2015-05-09) 67 | 68 | - 簡化 Vagrant 虛擬機數量。 69 | - 增加「極簡化 Docker」實例,解釋 rootfs、dependency 與 isolation 性質。 70 | 71 | 72 | **v3.0** / 第三梯次 (2015-04-11) 73 | 74 | - 簡化 Vagrant 環境設定程序。 75 | 76 | 77 | **v2.0** / 第二梯次 (2015-03-07) 78 | 79 | - 更新至 Docker 1.5.0。 80 | - 增加更多程式語言例子。 81 | - 增加 Docker Compose 例子。 82 | - 增加更適合的實例,解釋 dependency 與 isolation 性質。 83 | - 增加更適合的實例,逐步剖析 container linking 觀念。 84 | - 增加更適合的實例,逐步剖析 Dockerized app 要素。 85 | 86 | 87 | **v1.0** / 第一梯次 (2015-02-07) 88 | 89 | - 初版 90 | 91 | 92 | ## License 93 | 94 | Apache License V2.0. See [LICENSE](LICENSE) file for details. 95 | 96 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | Vagrant.require_version ">= 1.7.4" 2 | 3 | # change default synced_folder for convenience 4 | SYNCED_FOLDER = "/home/vagrant/docker-workshop" 5 | 6 | # expose ports from guest to host for convenience 7 | FORWARDED_PORT_RANGE = (10080..10100).to_a.push(10443).to_a.push(8080) 8 | 9 | # external provision script files 10 | PROVISION_SCRIPTS = [ "provision/setup-docker-tools.sh", "provision/setup-env.sh", "provision/setup-hosts.sh" ] 11 | 12 | 13 | Vagrant.configure(2) do |config| 14 | 15 | config.vm.define "main", primary: true do |node| 16 | 17 | node.vm.box = "williamyeh/ubuntu-trusty64-docker" 18 | node.vm.box_version = ">= 1.8.1" 19 | 20 | node.vm.network "private_network", ip: "10.0.0.10" 21 | 22 | for i in FORWARDED_PORT_RANGE 23 | node.vm.network "forwarded_port", guest: i, host: i 24 | end 25 | 26 | node.vm.synced_folder ".", SYNCED_FOLDER 27 | 28 | for f in PROVISION_SCRIPTS 29 | node.vm.provision "shell", path: f 30 | end 31 | 32 | node.vm.provider "virtualbox" do |vb| 33 | vb.customize ["modifyvm", :id, "--memory", "1024"] 34 | #vb.customize ["modifyvm", :id, "--memory", "2048"] 35 | end 36 | 37 | end 38 | 39 | 40 | 41 | config.vm.define "centos" do |node| 42 | node.vm.box = "bento/centos-5.11" 43 | node.vm.network "private_network", ip: "10.0.0.30" 44 | 45 | node.vm.synced_folder ".", SYNCED_FOLDER 46 | 47 | # [NOTE] unmark this while benchmarking VM startup time 48 | #node.vm.box_check_update = false 49 | 50 | node.vm.provider "virtualbox" do |vb| 51 | vb.customize ["modifyvm", :id, "--memory", "256"] 52 | end 53 | end 54 | 55 | 56 | 57 | config.vm.define "registry" do |node| 58 | 59 | node.vm.box = "williamyeh/docker-workshop-registry" 60 | node.vm.box_version = ">= 5.0.0" 61 | 62 | node.vm.network "private_network", ip: "10.0.0.200" 63 | 64 | node.vm.synced_folder ".", SYNCED_FOLDER 65 | 66 | for f in PROVISION_SCRIPTS 67 | node.vm.provision "shell", path: f 68 | end 69 | 70 | end 71 | 72 | 73 | end 74 | -------------------------------------------------------------------------------- /build-chat-onbuild/ABOUT-THIS-PATCH.md: -------------------------------------------------------------------------------- 1 | About this patch (ONBUILD version) 2 | === 3 | 4 | ## Introduction 5 | 6 | The original project [rauchg/chat-example](https://github.com/rauchg/chat-example) is a simple chatroom demo using Node.js + Socket.IO. 7 | 8 | I patch the code a little bit to "Dockerize" it. 9 | 10 | 11 | ## Patch for Docker 12 | 13 | 1. Add: `Dockerfile` 14 | 15 | 2. Patch `package.json`: add a "start" section. 16 | 17 | 18 | ## Reference 19 | 20 | `node:0.10.36-onbuild` Dockerfile: https://github.com/joyent/docker-node/blob/d23f190e500e91ecc636878a079ff971b29eab3e/0.10/onbuild/Dockerfile 21 | 22 | See [`node` official repo](https://registry.hub.docker.com/_/node/) at Docker Hub for more ONBUILD assumptions. 23 | -------------------------------------------------------------------------------- /build-chat-onbuild/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:0.10.36-onbuild 2 | 3 | EXPOSE 3000 4 | -------------------------------------------------------------------------------- /build-chat-onbuild/Dockerfile.official-0.10.36-onbuild: -------------------------------------------------------------------------------- 1 | FROM node:0.10.36 2 | 3 | RUN mkdir -p /usr/src/app 4 | WORKDIR /usr/src/app 5 | 6 | ONBUILD COPY package.json /usr/src/app/ 7 | ONBUILD RUN npm install 8 | ONBUILD COPY . /usr/src/app 9 | 10 | CMD [ "npm", "start" ] 11 | -------------------------------------------------------------------------------- /build-chat-onbuild/README.md: -------------------------------------------------------------------------------- 1 | # chat-example 2 | 3 | This is the source code for a very simple chat example used for 4 | the [Getting Started](http://socket.io/get-started/chat/) guide 5 | of the Socket.IO website. 6 | 7 | Please refer to it to learn how to run this application. 8 | -------------------------------------------------------------------------------- /build-chat-onbuild/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Socket.IO chat 5 | 15 | 16 | 17 | 18 |
19 | 20 |
21 | 22 | 23 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /build-chat-onbuild/index.js: -------------------------------------------------------------------------------- 1 | var app = require('express')(); 2 | var http = require('http').Server(app); 3 | var io = require('socket.io')(http); 4 | 5 | app.get('/', function(req, res){ 6 | res.sendFile(__dirname + '/index.html'); 7 | }); 8 | 9 | io.on('connection', function(socket){ 10 | socket.on('chat message', function(msg){ 11 | io.emit('chat message', msg); 12 | }); 13 | }); 14 | 15 | http.listen(3000, function(){ 16 | console.log('listening on *:3000'); 17 | }); 18 | -------------------------------------------------------------------------------- /build-chat-onbuild/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "socket-chat-example", 3 | "version": "0.0.1", 4 | "description": "my first socket.io app", 5 | "scripts": { 6 | "start": "node index.js" 7 | }, 8 | "dependencies": { 9 | "express": "4.10.2", 10 | "socket.io": "1.2.0" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /build-chat/.dockerignore: -------------------------------------------------------------------------------- 1 | *.md 2 | docker-compose.yml 3 | -------------------------------------------------------------------------------- /build-chat/ABOUT-THIS-PATCH.md: -------------------------------------------------------------------------------- 1 | About this patch 2 | === 3 | 4 | ## Introduction 5 | 6 | The original project [rauchg/chat-example](https://github.com/rauchg/chat-example) is a simple chatroom demo using Node.js + Socket.IO. 7 | 8 | I patch the code a little bit to "Dockerize" it. 9 | 10 | 11 | ## Patch for Docker 12 | 13 | 1. Add: `Dockerfile` 14 | 15 | 2. Patch `package.json`: add a "start" section. 16 | 17 | 18 | -------------------------------------------------------------------------------- /build-chat/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:0.10.36-slim 2 | 3 | RUN mkdir -p /app 4 | WORKDIR /app 5 | 6 | COPY package.json /app/ 7 | RUN npm install --production 8 | COPY . /app 9 | 10 | EXPOSE 3000 11 | CMD [ "npm", "start" ] 12 | -------------------------------------------------------------------------------- /build-chat/README.md: -------------------------------------------------------------------------------- 1 | # chat-example 2 | 3 | This is the source code for a very simple chat example used for 4 | the [Getting Started](http://socket.io/get-started/chat/) guide 5 | of the Socket.IO website. 6 | 7 | Please refer to it to learn how to run this application. 8 | -------------------------------------------------------------------------------- /build-chat/docker-compose.yml: -------------------------------------------------------------------------------- 1 | app: 2 | build: . 3 | ports: 4 | - "10080:3000" 5 | -------------------------------------------------------------------------------- /build-chat/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Socket.IO chat 5 | 15 | 16 | 17 | 18 |
19 | 20 |
21 | 22 | 23 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /build-chat/index.js: -------------------------------------------------------------------------------- 1 | var app = require('express')(); 2 | var http = require('http').Server(app); 3 | var io = require('socket.io')(http); 4 | 5 | app.get('/', function(req, res){ 6 | res.sendFile(__dirname + '/index.html'); 7 | }); 8 | 9 | io.on('connection', function(socket){ 10 | socket.on('chat message', function(msg){ 11 | io.emit('chat message', msg); 12 | }); 13 | }); 14 | 15 | http.listen(3000, function(){ 16 | console.log('listening on *:3000'); 17 | }); 18 | -------------------------------------------------------------------------------- /build-chat/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "socket-chat-example", 3 | "version": "0.0.1", 4 | "description": "my first socket.io app", 5 | "scripts": { 6 | "start": "node index.js" 7 | }, 8 | "dependencies": { 9 | "express": "4.10.2", 10 | "socket.io": "1.2.0" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /build-fork/.dockerignore: -------------------------------------------------------------------------------- 1 | output.txt 2 | -------------------------------------------------------------------------------- /build-fork/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:14.04 2 | 3 | COPY getpid /usr/local/bin/ 4 | COPY fork /usr/local/bin/ 5 | 6 | WORKDIR /data 7 | VOLUME ["/data"] 8 | 9 | CMD [ "getpid" ] 10 | -------------------------------------------------------------------------------- /build-fork/docker-compose.yml: -------------------------------------------------------------------------------- 1 | # normal case: 2 | # child exit first, parent exit last 3 | normal: 4 | build: . 5 | command: fork 5 0 6 | volumes: 7 | - .:/data 8 | 9 | # abnormal case: 10 | # parent exit first, child exit last (orphan) 11 | abnormal: 12 | build: . 13 | command: fork 0 5 14 | volumes: 15 | - .:/data 16 | 17 | -------------------------------------------------------------------------------- /build-fork/fork: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | use strict; 3 | use warnings; 4 | use English; # for $PID 5 | use File::Basename; 6 | 7 | 8 | my $fh; 9 | my $PARENT_TAG = "[Parent] "; 10 | my $CHILD_TAG = " [Child] "; 11 | 12 | # sleep period in seconds 13 | my ($parent_sleep, $child_sleep, $output_file) = @ARGV; 14 | 15 | sub main; 16 | sub child; 17 | sub my_tee; 18 | sub process_cmdline; 19 | sub usage; 20 | 21 | main(); 22 | 23 | sub main { 24 | process_cmdline(); 25 | 26 | my_tee $fh => ($PARENT_TAG, "PID = ", $PID, "\n"); 27 | 28 | my $pid = fork(); 29 | if ($pid == 0) { # We are the child 30 | child(); 31 | } 32 | elsif (defined($pid)) { # We are the parent of child 33 | my_tee $fh => ($PARENT_TAG, "forked a child with PID = $pid\n"); 34 | if ($parent_sleep > 0) { 35 | my_tee $fh => ($PARENT_TAG, "sleeping...\n"); 36 | sleep($parent_sleep); 37 | my_tee $fh => ($PARENT_TAG, "awaken!\n"); 38 | } 39 | my_tee $fh => ($PARENT_TAG, "exit...\n"); 40 | exit 0; 41 | } 42 | else { # The fork failed 43 | my_tee $fh => ($PARENT_TAG, "fork failed.\n"); 44 | exit 2; 45 | } 46 | } 47 | 48 | 49 | sub child { 50 | my_tee $fh => ($CHILD_TAG, "PID = ", $PID, "\n"); 51 | 52 | if ($child_sleep > 0) { 53 | my_tee $fh => ($CHILD_TAG, "sleeping...\n"); 54 | sleep($child_sleep); 55 | my_tee $fh => ($CHILD_TAG, "awaken!\n"); 56 | } 57 | 58 | my_tee $fh => ($CHILD_TAG, "exit...\n"); 59 | exit 0; 60 | } 61 | 62 | 63 | # simple "tee" function for Perl: 64 | # print the output on the screen and to a file 65 | # @see http://www.perlmonks.org/?node_id=962541 66 | sub my_tee { 67 | my $handle = shift; 68 | print $handle @_; 69 | print @_; 70 | } 71 | 72 | 73 | sub process_cmdline { 74 | usage() if (scalar @ARGV < 2); 75 | 76 | if (not defined $output_file) { 77 | $output_file = 'output.txt'; 78 | } 79 | 80 | open $fh, '>>', $output_file 81 | or die "$!"; 82 | 83 | my $now = localtime(); 84 | my_tee $fh => ("\n----> ", $now, " <----\n"); 85 | } 86 | 87 | 88 | sub usage { 89 | my $prog_name = basename($0); 90 | 91 | print < [output file] 93 | 94 | USAGE 95 | 96 | exit 1; 97 | } 98 | -------------------------------------------------------------------------------- /build-fork/getpid: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | use strict; 3 | use warnings; 4 | use English; # for $PID 5 | 6 | print $PID, "\n"; 7 | -------------------------------------------------------------------------------- /build-io/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM busybox 2 | 3 | COPY io.sh /usr/local/bin/ 4 | 5 | CMD ["io.sh"] 6 | -------------------------------------------------------------------------------- /build-io/README.md: -------------------------------------------------------------------------------- 1 | File I/O example 2 | === 3 | 4 | This directory demonstrates several Docker topics: 5 | 6 | - The usefulness of **volume** mechanism in Docker. 7 | - The `docker logs` command. 8 | 9 | 10 | ## Steps 11 | 12 | 1. Run without Docker 13 | 14 | ```bash 15 | $ ./io.sh 16 | $ ./io.sh 17 | $ ./io.sh 18 | 19 | $ cat /tmp/output 20 | ``` 21 | 22 | 23 | 2. Run with Docker, without volume mechanism 24 | 25 | ```bash 26 | $ docker build -t io . 27 | 28 | $ docker run io 29 | $ docker run io 30 | $ docker run io 31 | 32 | $ cat /tmp/output 33 | 34 | $ docker ps -a 35 | $ docker logs 36 | ``` 37 | 38 | 39 | 3. Run with Docker, with volume mechanism 40 | 41 | ```bash 42 | $ docker run -v $(pwd):/tmp io 43 | $ docker run -v $(pwd):/tmp io 44 | $ docker run -v $(pwd):/tmp io 45 | 46 | $ cat ./output 47 | 48 | $ docker ps -a 49 | $ docker logs 50 | ``` 51 | -------------------------------------------------------------------------------- /build-io/io.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Append date info to specified output file (default: "/tmp/output"), 4 | # and display its content. 5 | # 6 | 7 | 8 | OUTPUT=${1:-/tmp/output} 9 | 10 | # create output file, if not exist... 11 | if [ ! -f "$OUTPUT" ]; then 12 | touch $OUTPUT 13 | fi 14 | 15 | 16 | # append date info 17 | date >> $OUTPUT 18 | 19 | 20 | # display the content of output file 21 | cat $OUTPUT 22 | -------------------------------------------------------------------------------- /build-mcrypt/Dockerfile.nodejs: -------------------------------------------------------------------------------- 1 | # a naive image for Node.js + mcrypt 2 | 3 | FROM node:0.10.36-slim 4 | 5 | RUN mkdir -p /opt/node_modules 6 | WORKDIR /opt 7 | 8 | # copy to image/container 9 | COPY libmcrypt4_2.5.8-3.3_amd64.deb libmcrypt4.deb 10 | COPY libmcrypt-dev_2.5.8-3.3_amd64.deb libmcrypt-dev.deb 11 | 12 | # install from deb 13 | RUN dpkg -i libmcrypt4.deb libmcrypt-dev.deb 14 | 15 | # copy pre-installed Node.js modules 16 | COPY node_modules /opt/node_modules/ 17 | #COPY package.json /opt/ 18 | #RUN npm install 19 | 20 | # run! 21 | ENTRYPOINT ["node"] 22 | -------------------------------------------------------------------------------- /build-mcrypt/Dockerfile.official-5.6.6: -------------------------------------------------------------------------------- 1 | FROM debian:jessie 2 | 3 | # persistent / runtime deps 4 | RUN apt-get update && apt-get install -y ca-certificates curl libxml2 --no-install-recommends && rm -r /var/lib/apt/lists/* 5 | 6 | # phpize deps 7 | RUN apt-get update && apt-get install -y autoconf gcc make pkg-config --no-install-recommends && rm -r /var/lib/apt/lists/* 8 | 9 | ENV PHP_INI_DIR /usr/local/etc/php 10 | RUN mkdir -p $PHP_INI_DIR/conf.d 11 | 12 | #### 13 | #### 14 | 15 | RUN gpg --keyserver pool.sks-keyservers.net --recv-keys 6E4F6AB321FDC07F2C332E3AC2BF0BC433CFC8B3 0BD78B5F97500D450838F95DFE857D9A90D90EC1 16 | 17 | ENV PHP_VERSION 5.6.6 18 | 19 | # --enable-mysqlnd is included below because it's harder to compile after the fact the extensions are (since it's a plugin for several extensions, not an extension in itself) 20 | RUN buildDeps=" \ 21 | $PHP_EXTRA_BUILD_DEPS \ 22 | bzip2 \ 23 | file \ 24 | libcurl4-openssl-dev \ 25 | libreadline6-dev \ 26 | libssl-dev \ 27 | libxml2-dev \ 28 | "; \ 29 | set -x \ 30 | && apt-get update && apt-get install -y $buildDeps --no-install-recommends && rm -rf /var/lib/apt/lists/* \ 31 | && curl -SL "http://php.net/get/php-$PHP_VERSION.tar.bz2/from/this/mirror" -o php.tar.bz2 \ 32 | && curl -SL "http://php.net/get/php-$PHP_VERSION.tar.bz2.asc/from/this/mirror" -o php.tar.bz2.asc \ 33 | && gpg --verify php.tar.bz2.asc \ 34 | && mkdir -p /usr/src/php \ 35 | && tar -xf php.tar.bz2 -C /usr/src/php --strip-components=1 \ 36 | && rm php.tar.bz2* \ 37 | && cd /usr/src/php \ 38 | && ./configure \ 39 | --with-config-file-path="$PHP_INI_DIR" \ 40 | --with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \ 41 | $PHP_EXTRA_CONFIGURE_ARGS \ 42 | --disable-cgi \ 43 | --enable-mysqlnd \ 44 | --with-curl \ 45 | --with-openssl \ 46 | --with-readline \ 47 | --with-zlib \ 48 | && make -j"$(nproc)" \ 49 | && make install \ 50 | && { find /usr/local/bin /usr/local/sbin -type f -executable -exec strip --strip-all '{}' + || true; } \ 51 | && apt-get purge -y --auto-remove $buildDeps \ 52 | && make clean 53 | 54 | COPY docker-php-ext-* /usr/local/bin/ 55 | 56 | #### 57 | CMD ["php", "-a"] 58 | #### 59 | -------------------------------------------------------------------------------- /build-mcrypt/Dockerfile.php: -------------------------------------------------------------------------------- 1 | # a naive PHP + mcrypt image 2 | 3 | FROM php:5.6.6-cli 4 | 5 | # copy to image/container 6 | COPY libmcrypt4_2.5.8-3.1_amd64.deb libmcrypt4.deb 7 | COPY libmcrypt-dev_2.5.8-3.1_amd64.deb libmcrypt-dev.deb 8 | 9 | # install from deb 10 | RUN dpkg -i libmcrypt4.deb libmcrypt-dev.deb 11 | 12 | # install PHP modules 13 | # ... via a convenient wrapper for "make ; make install" stuff 14 | RUN docker-php-ext-install mcrypt 15 | 16 | 17 | # start PHP 18 | ENTRYPOINT [ "php" ] -------------------------------------------------------------------------------- /build-mcrypt/Dockerfile.php-new: -------------------------------------------------------------------------------- 1 | # a naive PHP + mcrypt image 2 | 3 | FROM php:5.6.6-cli 4 | 5 | # copy to image/container 6 | COPY libmcrypt4_2.5.8-3.3_amd64.deb libmcrypt4.deb 7 | COPY libmcrypt-dev_2.5.8-3.3_amd64.deb libmcrypt-dev.deb 8 | 9 | # install from deb 10 | RUN dpkg -i libmcrypt4.deb libmcrypt-dev.deb 11 | 12 | # install PHP modules 13 | # ... via a convenient wrapper for "make ; make install" stuff 14 | RUN docker-php-ext-install mcrypt 15 | 16 | 17 | # start PHP 18 | ENTRYPOINT [ "php" ] -------------------------------------------------------------------------------- /build-mcrypt/README.md: -------------------------------------------------------------------------------- 1 | Build a naive PHP/Node.js + mcrypt image for Ubuntu 14.04 LTS (Trusty) 2 | === 3 | 4 | 5 | ## Purpose 6 | 7 | Demostrate how to build a naive PHP/Node.js + mcrypt image from Dockerfile. 8 | 9 | This lab uses pre-downloaded DEB files to minimize time to completion. Alternatives have drawbacks for this lab: 10 | 11 | - Building from tarball source will require `build-essential`. 12 | - Installing by `apt-get` will require downloading packages on-the-fly. 13 | 14 | It is just a naive demo, especially in early workshop stages. For a better Dockerfile to learn from, see [official PHP repo](https://registry.hub.docker.com/_/php/) and [official Node.js repo](https://registry.hub.docker.com/_/node/). 15 | 16 | 17 | ## Package 18 | 19 | Package: [`libmcrypt4`](http://packages.ubuntu.com/trusty/libmcrypt4) and [`libmcrypt-dev`](http://packages.ubuntu.com/trusty/libmcrypt-dev) 20 | 21 | DEB files: see http://mirrors.kernel.org/ubuntu/pool/universe/libm/libmcrypt/ 22 | -------------------------------------------------------------------------------- /build-mcrypt/centos-nodejs-mcrypt/README.txt: -------------------------------------------------------------------------------- 1 | Demostrate how to build all dependencies for Node.js + mcrypt under CentOS. 2 | -------------------------------------------------------------------------------- /build-mcrypt/centos-nodejs-mcrypt/Vagrantfile: -------------------------------------------------------------------------------- 1 | Vagrant.configure(2) do |config| 2 | config.vm.box = "bento/centos-6.7" 3 | 4 | config.vm.provision "shell", inline: <<-SHELL 5 | rpm -ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm 6 | yum -y install libmcrypt-devel nodejs npm 7 | npm install mcrypt 8 | # vagrant ssh ; cd /vagrant 9 | # node example.js 10 | SHELL 11 | end 12 | -------------------------------------------------------------------------------- /build-mcrypt/centos-nodejs-mcrypt/example.js: -------------------------------------------------------------------------------- 1 | /** 2 | * simple demo for mcrypt in Node.js 3 | * adapted from PHP example: http://php.net/manual/en/function.mcrypt-encrypt.php 4 | */ 5 | 6 | var mcrypt = require('mcrypt'); 7 | 8 | var CIPHER_ALGO = 'rijndael-256'; 9 | var cipher = new mcrypt.MCrypt(CIPHER_ALGO, 'cbc'); 10 | 11 | 12 | 13 | var key = new Buffer( 14 | "bcb04b7e103a0cd8b54763051cef08bc55abe029fdebae5e1d417e2ffb2a00a3" 15 | , 'hex'); 16 | 17 | var iv = cipher.generateIv(); 18 | var iv_size = iv.length; 19 | 20 | console.log('Cipher:', CIPHER_ALGO); 21 | console.log('Key size:', key.length); 22 | console.log('Key:', key.toString('hex')); 23 | console.log('IV: ', iv.toString('hex')); 24 | console.log("---"); 25 | 26 | 27 | // display plaintext 28 | var plaintext = 'This string was AES-256 / CBC / ZeroBytePadding encrypted.'; 29 | console.log('Before encryption:', plaintext); 30 | 31 | 32 | // --- ENCRYPTION --- 33 | 34 | cipher.open(key, iv); 35 | 36 | var ciphertext = cipher.encrypt(plaintext); 37 | var combined = Buffer.concat([iv, ciphertext]); 38 | var ciphertext_base64 = combined.toString('base64'); 39 | console.log('After encryption: ', ciphertext_base64); 40 | 41 | 42 | // --- DECRYPTION --- 43 | 44 | var ciphertext_binary = new Buffer(ciphertext_base64, 'base64'); 45 | 46 | var iv_dec = new Buffer(iv_size); 47 | var ciphertext_dec = new Buffer(ciphertext_binary.length - iv_size); 48 | ciphertext_binary.copy(iv_dec, 0, 0, iv_size); 49 | ciphertext_binary.copy(ciphertext_dec, 0, iv_size); 50 | 51 | cipher.open(key, iv_dec); 52 | var plaintext_dec = cipher.decrypt(ciphertext_dec); 53 | console.log('After decryption: ', plaintext_dec.toString()); 54 | -------------------------------------------------------------------------------- /build-mcrypt/demo-nodejs: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | NODEJS_IMAGE=$1 4 | NODEJS_EXAMPLE=${2:-example.js} 5 | NAME=$(basename $BASH_SOURCE) 6 | 7 | if [ $# -lt 1 ]; then 8 | echo "Demo for Dockerized Node.js." 9 | echo "Usage: $NAME [nodejs source code]" 10 | exit 1 11 | fi 12 | 13 | cat $NODEJS_EXAMPLE | docker run -i $NODEJS_IMAGE 14 | -------------------------------------------------------------------------------- /build-mcrypt/demo-php: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PHP_IMAGE=$1 4 | PHP_EXAMPLE=${2:-example.php} 5 | NAME=$(basename $BASH_SOURCE) 6 | 7 | if [ $# -lt 1 ]; then 8 | echo "Demo for Dockerized PHP." 9 | echo "Usage: $NAME [php source code]" 10 | exit 1 11 | fi 12 | 13 | cat $PHP_EXAMPLE | docker run -i $PHP_IMAGE 14 | -------------------------------------------------------------------------------- /build-mcrypt/example.js: -------------------------------------------------------------------------------- 1 | /** 2 | * simple demo for mcrypt in Node.js 3 | * adapted from PHP example: http://php.net/manual/en/function.mcrypt-encrypt.php 4 | */ 5 | 6 | var mcrypt = require('mcrypt'); 7 | 8 | var CIPHER_ALGO = 'rijndael-256'; 9 | var cipher = new mcrypt.MCrypt(CIPHER_ALGO, 'cbc'); 10 | 11 | 12 | 13 | var key = new Buffer( 14 | "bcb04b7e103a0cd8b54763051cef08bc55abe029fdebae5e1d417e2ffb2a00a3" 15 | , 'hex'); 16 | 17 | var iv = cipher.generateIv(); 18 | var iv_size = iv.length; 19 | 20 | console.log('Cipher:', CIPHER_ALGO); 21 | console.log('Key size:', key.length); 22 | console.log('Key:', key.toString('hex')); 23 | console.log('IV: ', iv.toString('hex')); 24 | console.log("---"); 25 | 26 | 27 | // display plaintext 28 | var plaintext = 'This string was AES-256 / CBC / ZeroBytePadding encrypted.'; 29 | console.log('Before encryption:', plaintext); 30 | 31 | 32 | // --- ENCRYPTION --- 33 | 34 | cipher.open(key, iv); 35 | 36 | var ciphertext = cipher.encrypt(plaintext); 37 | var combined = Buffer.concat([iv, ciphertext]); 38 | var ciphertext_base64 = combined.toString('base64'); 39 | console.log('After encryption: ', ciphertext_base64); 40 | 41 | 42 | // --- DECRYPTION --- 43 | 44 | var ciphertext_binary = new Buffer(ciphertext_base64, 'base64'); 45 | 46 | var iv_dec = new Buffer(iv_size); 47 | var ciphertext_dec = new Buffer(ciphertext_binary.length - iv_size); 48 | ciphertext_binary.copy(iv_dec, 0, 0, iv_size); 49 | ciphertext_binary.copy(ciphertext_dec, 0, iv_size); 50 | 51 | cipher.open(key, iv_dec); 52 | var plaintext_dec = cipher.decrypt(ciphertext_dec); 53 | console.log('After decryption: ', plaintext_dec.toString()); 54 | -------------------------------------------------------------------------------- /build-mcrypt/example.php: -------------------------------------------------------------------------------- 1 | 75 | -------------------------------------------------------------------------------- /build-mcrypt/libmcrypt-dev_2.5.8-3.1_amd64.deb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/William-Yeh/docker-workshop/88c1d4b0674c3e1d2c2d6c3e2c02d406bcf6e791/build-mcrypt/libmcrypt-dev_2.5.8-3.1_amd64.deb -------------------------------------------------------------------------------- /build-mcrypt/libmcrypt-dev_2.5.8-3.3_amd64.deb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/William-Yeh/docker-workshop/88c1d4b0674c3e1d2c2d6c3e2c02d406bcf6e791/build-mcrypt/libmcrypt-dev_2.5.8-3.3_amd64.deb -------------------------------------------------------------------------------- /build-mcrypt/libmcrypt4_2.5.8-3.1_amd64.deb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/William-Yeh/docker-workshop/88c1d4b0674c3e1d2c2d6c3e2c02d406bcf6e791/build-mcrypt/libmcrypt4_2.5.8-3.1_amd64.deb -------------------------------------------------------------------------------- /build-mcrypt/libmcrypt4_2.5.8-3.3_amd64.deb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/William-Yeh/docker-workshop/88c1d4b0674c3e1d2c2d6c3e2c02d406bcf6e791/build-mcrypt/libmcrypt4_2.5.8-3.3_amd64.deb -------------------------------------------------------------------------------- /build-mcrypt/node_modules/mcrypt/.npmignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | *.swp 3 | .git -------------------------------------------------------------------------------- /build-mcrypt/node_modules/mcrypt/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Tuğrul Topuz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /build-mcrypt/node_modules/mcrypt/README.md: -------------------------------------------------------------------------------- 1 | # node-mcrypt 2 | 3 | MCrypt bindings for Node.js 4 | 5 | ## Dependencies 6 | 7 | ### Debian / Ubuntu 8 | 9 | ``` 10 | apt-get install libmcrypt4 libmcrypt-dev 11 | ``` 12 | 13 | ### OSX 14 | 15 | ``` 16 | brew install mcrypt 17 | ``` 18 | 19 | ## Install 20 | 21 | ``` 22 | npm install mcrypt 23 | ``` 24 | 25 | ## Introduction 26 | 27 | Alright! There is already OpenSSL extension bundled with Node.js but there are something wrong with some traditional encryption algorithms on OpenSSL. 28 | 29 | I tried to decrypt ciphertext of AES and DES algorithms using OpenSSL but i get the garbage outputs. There are some reasons with OpenSSL like null padding. 30 | 31 | Also i saw same issues on the stackoverflow.com. Some people encountered with same problems. 32 | 33 | This extension provide the cipher and decipher operations via `libmcrypt` and compatible with Java Crypto and PHP MCrypt consequently. 34 | 35 | You should start with import the package like 36 | 37 | ```javascript 38 | var mcrypt = require('mcrypt'); 39 | ``` 40 | 41 | There are 3 exposed common functions in the package. These functions are `getAlgorithmNames()`, `getModeNames()` and `MCrypt()` constructor function. Also there are some functions under the prototype of `MCrypt()` constructor function. 42 | 43 | ### getAlgorithmNames([path]) : Array 44 | 45 | `getAlgorithmNames()` returns an array that contains available algorithm names. `path` parameter to specify special algorithm directory. `path` parameter is not required. 46 | 47 | ```javascript 48 | var mcrypt = require('mcrypt'); 49 | 50 | var algos = mcrypt.getAlgorithmNames(); 51 | console.log(algos); 52 | ``` 53 | 54 | Expected result like that 55 | 56 | ``` 57 | [ 'cast-128', 'gost', 'rijndael-128', 'twofish', 'arcfour', 'cast-256', 'loki97', 'rijndael-192', 'saferplus', 'wake', 'blowfish-compat', 'des', 'rijndael-256', 'serpent', 'xtea', 'blowfish', 'enigma', 'rc2', 'tripledes' ] 58 | ``` 59 | 60 | ### getModeNames([path]) : Array 61 | 62 | `getModeNames()` returns an array that contains available mode names. `path` parameter to specify special mode directory. `path` parameter is not required. 63 | 64 | ```javascript 65 | var mcrypt = require('mcrypt'); 66 | 67 | var algos = mcrypt.getModeNames(); 68 | console.log(algos); 69 | ``` 70 | 71 | Expected result like that 72 | ``` 73 | [ 'cbc', 'cfb', 'ctr', 'ecb', 'ncfb', 'nofb', 'ofb', 'stream' ] 74 | ``` 75 | 76 | ### MCrypt(algorithm, mode [, algorithmDir] [, modeDir]) : Object 77 | 78 | `MCrypt(algorithm, mode)` is a constructor function to create object for cipher and decipher operations. 79 | `algorithm` is a required parameter and one of the values of array returned by `getAlgorithmNames()`. 80 | `mode` is required parameter and one of the values of array returned by `getModeNames()`. 81 | `algorithmDir` and `modeDir` are optional parameters to specify algorithm and mode directories. 82 | 83 | ```javascript 84 | var MCrypt = require('mcrypt').MCrypt; 85 | 86 | var desEcb = new MCrypt('des', 'ecb'); 87 | ``` 88 | 89 | There are some prototype functions to make cipher decipher operations and to identify algorithm properties. 90 | 91 | #### open(key [, iv]) 92 | 93 | We are need to `open()` with a key for `decrypt()` and `encrypt()` operations also we should set an iv if required by algorithm in other case `iv` is optional parameter. 94 | `key` and `iv` should be string or Buffer 95 | 96 | ```javascript 97 | var MCrypt = require('mcrypt').MCrypt; 98 | 99 | var desEcb = new MCrypt('des', 'ecb'); 100 | desEcb.open('madepass'); // we are set the key 101 | ``` 102 | 103 | #### encrypt(plaintext) : Buffer 104 | 105 | `encrypt()` returns a Buffer object that contains ciphertext of `plaintext` parameter. `plaintext` parameter should be `string` or `Buffer` 106 | 107 | ```javascript 108 | var MCrypt = require('mcrypt').MCrypt; 109 | 110 | var desEcb = new MCrypt('des', 'ecb'); 111 | desEcb.open('madepass'); // we are set the key 112 | 113 | var ciphertext = desEcb.encrypt('this is top secret message!'); 114 | console.log(ciphertext.toString('base64')); 115 | ``` 116 | 117 | Expected result like that 118 | 119 | ``` 120 | fkJnIgtiH8nsGDryyuIsmyf5vABMGStlpACfKCTifvA= 121 | ``` 122 | 123 | #### decrypt(ciphertext) : Buffer 124 | 125 | `decrypt()` returns a Buffer object that contains plaintext of `ciphertext` parameter. `ciphertext` parameter should be `Buffer` 126 | 127 | ```javascript 128 | var MCrypt = require('mcrypt').MCrypt; 129 | 130 | var desEcb = new MCrypt('des', 'ecb'); 131 | desEcb.open('madepass'); // we are set the key 132 | 133 | var plaintext = desEcb.decrypt(new Buffer('fkJnIgtiH8nsGDryyuIsmyf5vABMGStlpACfKCTifvA=', 'base64')); 134 | console.log(plaintext.toString()); 135 | ``` 136 | 137 | Expected result like that 138 | 139 | ``` 140 | this is top secret message! 141 | ``` 142 | 143 | #### generateIv() : Buffer 144 | 145 | `generateIv()` function generates IV randomly. 146 | 147 | ```javascript 148 | var MCrypt = require('mcrypt').MCrypt; 149 | 150 | var blowfishCfb = new MCrypt('blowfish', 'cfb'); 151 | var iv = blowfishCfb.generateIv(); 152 | 153 | blowfishCfb.open('somekey', iv); 154 | 155 | var ciphertext = blowfishCfb.encrypt('sometext'); 156 | 157 | console.log(Buffer.concat([iv, ciphertext]).toString('base64')); 158 | ``` 159 | 160 | #### validateKeySize(Boolean) 161 | `validateKeySize()` is a function to disable or enable key size validation on `open()` 162 | 163 | ```javascript 164 | var mc = new MCrypt('blowfish', 'ecb'); 165 | mc.validateKeySize(false); // disable key size checking 166 | mc.open('typeconfig.sys^_-'); 167 | ``` 168 | 169 | #### validateIvSize(Boolean) 170 | `validateIvSize()` is a function to disable or enable iv size validation on `open()` 171 | 172 | ```javascript 173 | var mc = new MCrypt('rijndael-256', 'cbc'); 174 | mc.validateIvSize(false); // disable iv size checking 175 | mc.open('$verysec$retkey$', 'foobar'); 176 | ``` 177 | 178 | #### selfTest() : Boolean 179 | 180 | `selfTest()` is an utility function to make test algorithm internally and returns boolean value of status 181 | 182 | ```javascript 183 | var MCrypt = require('mcrypt').MCrypt; 184 | 185 | var blowfishCfb = new MCrypt('blowfish', 'cfb'); 186 | console.log(blowfishCfb.selfTest()); 187 | ``` 188 | 189 | #### isBlockAlgorithmMode() : Boolean 190 | 191 | ```javascript 192 | var MCrypt = require('mcrypt').MCrypt; 193 | 194 | var blowfishCfb = new MCrypt('blowfish', 'cfb'); 195 | console.log(blowfishCfb.isBlockAlgorithmMode()); 196 | ``` 197 | 198 | #### isBlockAlgorithm() : Boolean 199 | 200 | ```javascript 201 | var MCrypt = require('mcrypt').MCrypt; 202 | 203 | var blowfishCfb = new MCrypt('blowfish', 'cfb'); 204 | console.log(blowfishCfb.isBlockAlgorithm()); 205 | ``` 206 | 207 | #### isBlockMode() : Boolean 208 | 209 | ```javascript 210 | var MCrypt = require('mcrypt').MCrypt; 211 | 212 | var blowfishCfb = new MCrypt('blowfish', 'cfb'); 213 | console.log(blowfishCfb.isBlockMode()); 214 | ``` 215 | 216 | #### getBlockSize() : Number 217 | 218 | ```javascript 219 | var MCrypt = require('mcrypt').MCrypt; 220 | 221 | var blowfishCfb = new MCrypt('blowfish', 'cfb'); 222 | console.log(blowfishCfb.getBlockSize()); 223 | ``` 224 | 225 | #### getKeySize() : Number 226 | 227 | ```javascript 228 | var MCrypt = require('mcrypt').MCrypt; 229 | 230 | var blowfishCfb = new MCrypt('blowfish', 'cfb'); 231 | console.log(blowfishCfb.getKeySize()); 232 | ``` 233 | 234 | #### getSupportedKeySizes() : Array 235 | 236 | ```javascript 237 | var MCrypt = require('mcrypt').MCrypt; 238 | 239 | var blowfishCfb = new MCrypt('blowfish', 'cfb'); 240 | console.log(blowfishCfb.getSupportedKeySizes()); 241 | ``` 242 | 243 | #### getIvSize() : Number 244 | 245 | ```javascript 246 | var MCrypt = require('mcrypt').MCrypt; 247 | 248 | var blowfishCfb = new MCrypt('blowfish', 'cfb'); 249 | console.log(blowfishCfb.getIvSize()); 250 | ``` 251 | 252 | #### hasIv() : Boolean 253 | 254 | ```javascript 255 | var MCrypt = require('mcrypt').MCrypt; 256 | 257 | var blowfishCfb = new MCrypt('blowfish', 'cfb'); 258 | console.log(blowfishCfb.hasIv()); 259 | ``` 260 | 261 | #### getAlgorithmName() : String 262 | 263 | ```javascript 264 | var MCrypt = require('mcrypt').MCrypt; 265 | 266 | var blowfishCfb = new MCrypt('blowfish', 'cfb'); 267 | console.log(blowfishCfb.getAlgorithmName()); 268 | ``` 269 | 270 | #### getModeName() : String 271 | 272 | ```javascript 273 | var MCrypt = require('mcrypt').MCrypt; 274 | 275 | var blowfishCfb = new MCrypt('blowfish', 'cfb'); 276 | console.log(blowfishCfb.getModeName()); 277 | ``` 278 | 279 | -------------------------------------------------------------------------------- /build-mcrypt/node_modules/mcrypt/binding.gyp: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "target_name": "mcrypt", 5 | "sources": [ 6 | "src/mcrypt.cc" 7 | ], 8 | "include_dirs": [ 9 | "/usr/include/", 10 | "/opt/local/include/", 11 | "/usr/local/Cellar/mcrypt/" 12 | ], 13 | "link_settings": { 14 | "libraries": [ 15 | "-lmcrypt" 16 | ] 17 | } 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /build-mcrypt/node_modules/mcrypt/build/Makefile: -------------------------------------------------------------------------------- 1 | # We borrow heavily from the kernel build setup, though we are simpler since 2 | # we don't have Kconfig tweaking settings on us. 3 | 4 | # The implicit make rules have it looking for RCS files, among other things. 5 | # We instead explicitly write all the rules we care about. 6 | # It's even quicker (saves ~200ms) to pass -r on the command line. 7 | MAKEFLAGS=-r 8 | 9 | # The source directory tree. 10 | srcdir := .. 11 | abs_srcdir := $(abspath $(srcdir)) 12 | 13 | # The name of the builddir. 14 | builddir_name ?= . 15 | 16 | # The V=1 flag on command line makes us verbosely print command lines. 17 | ifdef V 18 | quiet= 19 | else 20 | quiet=quiet_ 21 | endif 22 | 23 | # Specify BUILDTYPE=Release on the command line for a release build. 24 | BUILDTYPE ?= Release 25 | 26 | # Directory all our build output goes into. 27 | # Note that this must be two directories beneath src/ for unit tests to pass, 28 | # as they reach into the src/ directory for data with relative paths. 29 | builddir ?= $(builddir_name)/$(BUILDTYPE) 30 | abs_builddir := $(abspath $(builddir)) 31 | depsdir := $(builddir)/.deps 32 | 33 | # Object output directory. 34 | obj := $(builddir)/obj 35 | abs_obj := $(abspath $(obj)) 36 | 37 | # We build up a list of every single one of the targets so we can slurp in the 38 | # generated dependency rule Makefiles in one pass. 39 | all_deps := 40 | 41 | 42 | 43 | CC.target ?= $(CC) 44 | CFLAGS.target ?= $(CFLAGS) 45 | CXX.target ?= $(CXX) 46 | CXXFLAGS.target ?= $(CXXFLAGS) 47 | LINK.target ?= $(LINK) 48 | LDFLAGS.target ?= $(LDFLAGS) 49 | AR.target ?= $(AR) 50 | 51 | # C++ apps need to be linked with g++. 52 | # 53 | # Note: flock is used to seralize linking. Linking is a memory-intensive 54 | # process so running parallel links can often lead to thrashing. To disable 55 | # the serialization, override LINK via an envrionment variable as follows: 56 | # 57 | # export LINK=g++ 58 | # 59 | # This will allow make to invoke N linker processes as specified in -jN. 60 | LINK ?= flock $(builddir)/linker.lock $(CXX.target) 61 | 62 | # TODO(evan): move all cross-compilation logic to gyp-time so we don't need 63 | # to replicate this environment fallback in make as well. 64 | CC.host ?= gcc 65 | CFLAGS.host ?= 66 | CXX.host ?= g++ 67 | CXXFLAGS.host ?= 68 | LINK.host ?= $(CXX.host) 69 | LDFLAGS.host ?= 70 | AR.host ?= ar 71 | 72 | # Define a dir function that can handle spaces. 73 | # http://www.gnu.org/software/make/manual/make.html#Syntax-of-Functions 74 | # "leading spaces cannot appear in the text of the first argument as written. 75 | # These characters can be put into the argument value by variable substitution." 76 | empty := 77 | space := $(empty) $(empty) 78 | 79 | # http://stackoverflow.com/questions/1189781/using-make-dir-or-notdir-on-a-path-with-spaces 80 | replace_spaces = $(subst $(space),?,$1) 81 | unreplace_spaces = $(subst ?,$(space),$1) 82 | dirx = $(call unreplace_spaces,$(dir $(call replace_spaces,$1))) 83 | 84 | # Flags to make gcc output dependency info. Note that you need to be 85 | # careful here to use the flags that ccache and distcc can understand. 86 | # We write to a dep file on the side first and then rename at the end 87 | # so we can't end up with a broken dep file. 88 | depfile = $(depsdir)/$(call replace_spaces,$@).d 89 | DEPFLAGS = -MMD -MF $(depfile).raw 90 | 91 | # We have to fixup the deps output in a few ways. 92 | # (1) the file output should mention the proper .o file. 93 | # ccache or distcc lose the path to the target, so we convert a rule of 94 | # the form: 95 | # foobar.o: DEP1 DEP2 96 | # into 97 | # path/to/foobar.o: DEP1 DEP2 98 | # (2) we want missing files not to cause us to fail to build. 99 | # We want to rewrite 100 | # foobar.o: DEP1 DEP2 \ 101 | # DEP3 102 | # to 103 | # DEP1: 104 | # DEP2: 105 | # DEP3: 106 | # so if the files are missing, they're just considered phony rules. 107 | # We have to do some pretty insane escaping to get those backslashes 108 | # and dollar signs past make, the shell, and sed at the same time. 109 | # Doesn't work with spaces, but that's fine: .d files have spaces in 110 | # their names replaced with other characters. 111 | define fixup_dep 112 | # The depfile may not exist if the input file didn't have any #includes. 113 | touch $(depfile).raw 114 | # Fixup path as in (1). 115 | sed -e "s|^$(notdir $@)|$@|" $(depfile).raw >> $(depfile) 116 | # Add extra rules as in (2). 117 | # We remove slashes and replace spaces with new lines; 118 | # remove blank lines; 119 | # delete the first line and append a colon to the remaining lines. 120 | sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\ 121 | grep -v '^$$' |\ 122 | sed -e 1d -e 's|$$|:|' \ 123 | >> $(depfile) 124 | rm $(depfile).raw 125 | endef 126 | 127 | # Command definitions: 128 | # - cmd_foo is the actual command to run; 129 | # - quiet_cmd_foo is the brief-output summary of the command. 130 | 131 | quiet_cmd_cc = CC($(TOOLSET)) $@ 132 | cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $@ $< 133 | 134 | quiet_cmd_cxx = CXX($(TOOLSET)) $@ 135 | cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< 136 | 137 | quiet_cmd_touch = TOUCH $@ 138 | cmd_touch = touch $@ 139 | 140 | quiet_cmd_copy = COPY $@ 141 | # send stderr to /dev/null to ignore messages when linking directories. 142 | cmd_copy = rm -rf "$@" && cp -af "$<" "$@" 143 | 144 | quiet_cmd_alink = AR($(TOOLSET)) $@ 145 | cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) crs $@ $(filter %.o,$^) 146 | 147 | quiet_cmd_alink_thin = AR($(TOOLSET)) $@ 148 | cmd_alink_thin = rm -f $@ && $(AR.$(TOOLSET)) crsT $@ $(filter %.o,$^) 149 | 150 | # Due to circular dependencies between libraries :(, we wrap the 151 | # special "figure out circular dependencies" flags around the entire 152 | # input list during linking. 153 | quiet_cmd_link = LINK($(TOOLSET)) $@ 154 | cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ -Wl,--start-group $(LD_INPUTS) -Wl,--end-group $(LIBS) 155 | 156 | # We support two kinds of shared objects (.so): 157 | # 1) shared_library, which is just bundling together many dependent libraries 158 | # into a link line. 159 | # 2) loadable_module, which is generating a module intended for dlopen(). 160 | # 161 | # They differ only slightly: 162 | # In the former case, we want to package all dependent code into the .so. 163 | # In the latter case, we want to package just the API exposed by the 164 | # outermost module. 165 | # This means shared_library uses --whole-archive, while loadable_module doesn't. 166 | # (Note that --whole-archive is incompatible with the --start-group used in 167 | # normal linking.) 168 | 169 | # Other shared-object link notes: 170 | # - Set SONAME to the library filename so our binaries don't reference 171 | # the local, absolute paths used on the link command-line. 172 | quiet_cmd_solink = SOLINK($(TOOLSET)) $@ 173 | cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--whole-archive $(LD_INPUTS) -Wl,--no-whole-archive $(LIBS) 174 | 175 | quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@ 176 | cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS) 177 | 178 | 179 | # Define an escape_quotes function to escape single quotes. 180 | # This allows us to handle quotes properly as long as we always use 181 | # use single quotes and escape_quotes. 182 | escape_quotes = $(subst ','\'',$(1)) 183 | # This comment is here just to include a ' to unconfuse syntax highlighting. 184 | # Define an escape_vars function to escape '$' variable syntax. 185 | # This allows us to read/write command lines with shell variables (e.g. 186 | # $LD_LIBRARY_PATH), without triggering make substitution. 187 | escape_vars = $(subst $$,$$$$,$(1)) 188 | # Helper that expands to a shell command to echo a string exactly as it is in 189 | # make. This uses printf instead of echo because printf's behaviour with respect 190 | # to escape sequences is more portable than echo's across different shells 191 | # (e.g., dash, bash). 192 | exact_echo = printf '%s\n' '$(call escape_quotes,$(1))' 193 | 194 | # Helper to compare the command we're about to run against the command 195 | # we logged the last time we ran the command. Produces an empty 196 | # string (false) when the commands match. 197 | # Tricky point: Make has no string-equality test function. 198 | # The kernel uses the following, but it seems like it would have false 199 | # positives, where one string reordered its arguments. 200 | # arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \ 201 | # $(filter-out $(cmd_$@), $(cmd_$(1)))) 202 | # We instead substitute each for the empty string into the other, and 203 | # say they're equal if both substitutions produce the empty string. 204 | # .d files contain ? instead of spaces, take that into account. 205 | command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\ 206 | $(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1)))) 207 | 208 | # Helper that is non-empty when a prerequisite changes. 209 | # Normally make does this implicitly, but we force rules to always run 210 | # so we can check their command lines. 211 | # $? -- new prerequisites 212 | # $| -- order-only dependencies 213 | prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?)) 214 | 215 | # Helper that executes all postbuilds until one fails. 216 | define do_postbuilds 217 | @E=0;\ 218 | for p in $(POSTBUILDS); do\ 219 | eval $$p;\ 220 | E=$$?;\ 221 | if [ $$E -ne 0 ]; then\ 222 | break;\ 223 | fi;\ 224 | done;\ 225 | if [ $$E -ne 0 ]; then\ 226 | rm -rf "$@";\ 227 | exit $$E;\ 228 | fi 229 | endef 230 | 231 | # do_cmd: run a command via the above cmd_foo names, if necessary. 232 | # Should always run for a given target to handle command-line changes. 233 | # Second argument, if non-zero, makes it do asm/C/C++ dependency munging. 234 | # Third argument, if non-zero, makes it do POSTBUILDS processing. 235 | # Note: We intentionally do NOT call dirx for depfile, since it contains ? for 236 | # spaces already and dirx strips the ? characters. 237 | define do_cmd 238 | $(if $(or $(command_changed),$(prereq_changed)), 239 | @$(call exact_echo, $($(quiet)cmd_$(1))) 240 | @mkdir -p "$(call dirx,$@)" "$(dir $(depfile))" 241 | $(if $(findstring flock,$(word 1,$(cmd_$1))), 242 | @$(cmd_$(1)) 243 | @echo " $(quiet_cmd_$(1)): Finished", 244 | @$(cmd_$(1)) 245 | ) 246 | @$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile) 247 | @$(if $(2),$(fixup_dep)) 248 | $(if $(and $(3), $(POSTBUILDS)), 249 | $(call do_postbuilds) 250 | ) 251 | ) 252 | endef 253 | 254 | # Declare the "all" target first so it is the default, 255 | # even though we don't have the deps yet. 256 | .PHONY: all 257 | all: 258 | 259 | # make looks for ways to re-generate included makefiles, but in our case, we 260 | # don't have a direct way. Explicitly telling make that it has nothing to do 261 | # for them makes it go faster. 262 | %.d: ; 263 | 264 | # Use FORCE_DO_CMD to force a target to run. Should be coupled with 265 | # do_cmd. 266 | .PHONY: FORCE_DO_CMD 267 | FORCE_DO_CMD: 268 | 269 | TOOLSET := target 270 | # Suffix rules, putting all outputs into $(obj). 271 | $(obj).$(TOOLSET)/%.o: $(srcdir)/%.c FORCE_DO_CMD 272 | @$(call do_cmd,cc,1) 273 | $(obj).$(TOOLSET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD 274 | @$(call do_cmd,cxx,1) 275 | $(obj).$(TOOLSET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD 276 | @$(call do_cmd,cxx,1) 277 | $(obj).$(TOOLSET)/%.o: $(srcdir)/%.cxx FORCE_DO_CMD 278 | @$(call do_cmd,cxx,1) 279 | $(obj).$(TOOLSET)/%.o: $(srcdir)/%.S FORCE_DO_CMD 280 | @$(call do_cmd,cc,1) 281 | $(obj).$(TOOLSET)/%.o: $(srcdir)/%.s FORCE_DO_CMD 282 | @$(call do_cmd,cc,1) 283 | 284 | # Try building from generated source, too. 285 | $(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD 286 | @$(call do_cmd,cc,1) 287 | $(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD 288 | @$(call do_cmd,cxx,1) 289 | $(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cpp FORCE_DO_CMD 290 | @$(call do_cmd,cxx,1) 291 | $(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cxx FORCE_DO_CMD 292 | @$(call do_cmd,cxx,1) 293 | $(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.S FORCE_DO_CMD 294 | @$(call do_cmd,cc,1) 295 | $(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.s FORCE_DO_CMD 296 | @$(call do_cmd,cc,1) 297 | 298 | $(obj).$(TOOLSET)/%.o: $(obj)/%.c FORCE_DO_CMD 299 | @$(call do_cmd,cc,1) 300 | $(obj).$(TOOLSET)/%.o: $(obj)/%.cc FORCE_DO_CMD 301 | @$(call do_cmd,cxx,1) 302 | $(obj).$(TOOLSET)/%.o: $(obj)/%.cpp FORCE_DO_CMD 303 | @$(call do_cmd,cxx,1) 304 | $(obj).$(TOOLSET)/%.o: $(obj)/%.cxx FORCE_DO_CMD 305 | @$(call do_cmd,cxx,1) 306 | $(obj).$(TOOLSET)/%.o: $(obj)/%.S FORCE_DO_CMD 307 | @$(call do_cmd,cc,1) 308 | $(obj).$(TOOLSET)/%.o: $(obj)/%.s FORCE_DO_CMD 309 | @$(call do_cmd,cc,1) 310 | 311 | 312 | ifeq ($(strip $(foreach prefix,$(NO_LOAD),\ 313 | $(findstring $(join ^,$(prefix)),\ 314 | $(join ^,mcrypt.target.mk)))),) 315 | include mcrypt.target.mk 316 | endif 317 | 318 | quiet_cmd_regen_makefile = ACTION Regenerating $@ 319 | cmd_regen_makefile = cd $(srcdir); /home/vagrant/.nvm/v0.10.36/lib/node_modules/npm/node_modules/node-gyp/gyp/gyp_main.py -fmake --ignore-environment "--toplevel-dir=." -I/home/vagrant/docker-workshop/build-php/node_modules/mcrypt/build/config.gypi -I/home/vagrant/.nvm/v0.10.36/lib/node_modules/npm/node_modules/node-gyp/addon.gypi -I/home/vagrant/.node-gyp/0.10.36/common.gypi "--depth=." "-Goutput_dir=." "--generator-output=build" "-Dlibrary=shared_library" "-Dvisibility=default" "-Dnode_root_dir=/home/vagrant/.node-gyp/0.10.36" "-Dmodule_root_dir=/home/vagrant/docker-workshop/build-php/node_modules/mcrypt" binding.gyp 320 | Makefile: $(srcdir)/../../../../.node-gyp/0.10.36/common.gypi $(srcdir)/build/config.gypi $(srcdir)/binding.gyp $(srcdir)/../../../../.nvm/v0.10.36/lib/node_modules/npm/node_modules/node-gyp/addon.gypi 321 | $(call do_cmd,regen_makefile) 322 | 323 | # "all" is a concatenation of the "all" targets from all the included 324 | # sub-makefiles. This is just here to clarify. 325 | all: 326 | 327 | # Add in dependency-tracking rules. $(all_deps) is the list of every single 328 | # target in our tree. Only consider the ones with .d (dependency) info: 329 | d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d)) 330 | ifneq ($(d_files),) 331 | include $(d_files) 332 | endif 333 | -------------------------------------------------------------------------------- /build-mcrypt/node_modules/mcrypt/build/Release/.deps/Release/mcrypt.node.d: -------------------------------------------------------------------------------- 1 | cmd_Release/mcrypt.node := rm -rf "Release/mcrypt.node" && cp -af "Release/obj.target/mcrypt.node" "Release/mcrypt.node" 2 | -------------------------------------------------------------------------------- /build-mcrypt/node_modules/mcrypt/build/Release/.deps/Release/obj.target/mcrypt.node.d: -------------------------------------------------------------------------------- 1 | cmd_Release/obj.target/mcrypt.node := flock ./Release/linker.lock g++ -shared -pthread -rdynamic -m64 -Wl,-soname=mcrypt.node -o Release/obj.target/mcrypt.node -Wl,--start-group Release/obj.target/mcrypt/src/mcrypt.o -Wl,--end-group -lmcrypt 2 | -------------------------------------------------------------------------------- /build-mcrypt/node_modules/mcrypt/build/Release/.deps/Release/obj.target/mcrypt/src/mcrypt.o.d: -------------------------------------------------------------------------------- 1 | cmd_Release/obj.target/mcrypt/src/mcrypt.o := g++ '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-DBUILDING_NODE_EXTENSION' -I/home/vagrant/.node-gyp/0.10.36/src -I/home/vagrant/.node-gyp/0.10.36/deps/uv/include -I/home/vagrant/.node-gyp/0.10.36/deps/v8/include -I/usr/include -I/opt/local/include -I/usr/local/Cellar/mcrypt -fPIC -Wall -Wextra -Wno-unused-parameter -pthread -m64 -O2 -fno-strict-aliasing -fno-tree-vrp -fno-tree-sink -fno-omit-frame-pointer -fno-rtti -fno-exceptions -MMD -MF ./Release/.deps/Release/obj.target/mcrypt/src/mcrypt.o.d.raw -c -o Release/obj.target/mcrypt/src/mcrypt.o ../src/mcrypt.cc 2 | Release/obj.target/mcrypt/src/mcrypt.o: ../src/mcrypt.cc ../src/mcrypt.h \ 3 | /home/vagrant/.node-gyp/0.10.36/src/node.h \ 4 | /home/vagrant/.node-gyp/0.10.36/deps/uv/include/uv.h \ 5 | /home/vagrant/.node-gyp/0.10.36/deps/uv/include/uv-private/uv-unix.h \ 6 | /home/vagrant/.node-gyp/0.10.36/deps/uv/include/uv-private/ngx-queue.h \ 7 | /home/vagrant/.node-gyp/0.10.36/deps/uv/include/uv-private/uv-linux.h \ 8 | /home/vagrant/.node-gyp/0.10.36/deps/v8/include/v8.h \ 9 | /home/vagrant/.node-gyp/0.10.36/deps/v8/include/v8stdint.h \ 10 | /home/vagrant/.node-gyp/0.10.36/src/node_object_wrap.h \ 11 | /home/vagrant/.node-gyp/0.10.36/src/node.h \ 12 | /home/vagrant/.node-gyp/0.10.36/src/node_buffer.h 13 | ../src/mcrypt.cc: 14 | ../src/mcrypt.h: 15 | /home/vagrant/.node-gyp/0.10.36/src/node.h: 16 | /home/vagrant/.node-gyp/0.10.36/deps/uv/include/uv.h: 17 | /home/vagrant/.node-gyp/0.10.36/deps/uv/include/uv-private/uv-unix.h: 18 | /home/vagrant/.node-gyp/0.10.36/deps/uv/include/uv-private/ngx-queue.h: 19 | /home/vagrant/.node-gyp/0.10.36/deps/uv/include/uv-private/uv-linux.h: 20 | /home/vagrant/.node-gyp/0.10.36/deps/v8/include/v8.h: 21 | /home/vagrant/.node-gyp/0.10.36/deps/v8/include/v8stdint.h: 22 | /home/vagrant/.node-gyp/0.10.36/src/node_object_wrap.h: 23 | /home/vagrant/.node-gyp/0.10.36/src/node.h: 24 | /home/vagrant/.node-gyp/0.10.36/src/node_buffer.h: 25 | -------------------------------------------------------------------------------- /build-mcrypt/node_modules/mcrypt/build/Release/linker.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/William-Yeh/docker-workshop/88c1d4b0674c3e1d2c2d6c3e2c02d406bcf6e791/build-mcrypt/node_modules/mcrypt/build/Release/linker.lock -------------------------------------------------------------------------------- /build-mcrypt/node_modules/mcrypt/build/Release/mcrypt.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/William-Yeh/docker-workshop/88c1d4b0674c3e1d2c2d6c3e2c02d406bcf6e791/build-mcrypt/node_modules/mcrypt/build/Release/mcrypt.node -------------------------------------------------------------------------------- /build-mcrypt/node_modules/mcrypt/build/Release/obj.target/mcrypt.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/William-Yeh/docker-workshop/88c1d4b0674c3e1d2c2d6c3e2c02d406bcf6e791/build-mcrypt/node_modules/mcrypt/build/Release/obj.target/mcrypt.node -------------------------------------------------------------------------------- /build-mcrypt/node_modules/mcrypt/build/Release/obj.target/mcrypt/src/mcrypt.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/William-Yeh/docker-workshop/88c1d4b0674c3e1d2c2d6c3e2c02d406bcf6e791/build-mcrypt/node_modules/mcrypt/build/Release/obj.target/mcrypt/src/mcrypt.o -------------------------------------------------------------------------------- /build-mcrypt/node_modules/mcrypt/build/binding.Makefile: -------------------------------------------------------------------------------- 1 | # This file is generated by gyp; do not edit. 2 | 3 | export builddir_name ?= ./build/. 4 | .PHONY: all 5 | all: 6 | $(MAKE) mcrypt 7 | -------------------------------------------------------------------------------- /build-mcrypt/node_modules/mcrypt/build/config.gypi: -------------------------------------------------------------------------------- 1 | # Do not edit. File was generated by node-gyp's "configure" step 2 | { 3 | "target_defaults": { 4 | "cflags": [], 5 | "default_configuration": "Release", 6 | "defines": [], 7 | "include_dirs": [], 8 | "libraries": [] 9 | }, 10 | "variables": { 11 | "clang": 0, 12 | "gcc_version": 44, 13 | "host_arch": "x64", 14 | "node_install_npm": "true", 15 | "node_prefix": "/", 16 | "node_shared_cares": "false", 17 | "node_shared_http_parser": "false", 18 | "node_shared_libuv": "false", 19 | "node_shared_openssl": "false", 20 | "node_shared_v8": "false", 21 | "node_shared_zlib": "false", 22 | "node_tag": "", 23 | "node_unsafe_optimizations": 0, 24 | "node_use_dtrace": "false", 25 | "node_use_etw": "false", 26 | "node_use_openssl": "true", 27 | "node_use_perfctr": "false", 28 | "node_use_systemtap": "false", 29 | "openssl_no_asm": 0, 30 | "python": "/data/opt/bin/python", 31 | "target_arch": "x64", 32 | "v8_enable_gdbjit": 0, 33 | "v8_no_strict_aliasing": 1, 34 | "v8_use_snapshot": "false", 35 | "want_separate_host_toolset": 0, 36 | "nodedir": "/home/vagrant/.node-gyp/0.10.36", 37 | "copy_dev_lib": "true", 38 | "standalone_static_library": 1, 39 | "cache_lock_stale": "60000", 40 | "sign_git_tag": "", 41 | "user_agent": "npm/1.4.28 node/v0.10.36 linux x64", 42 | "always_auth": "", 43 | "bin_links": "true", 44 | "key": "", 45 | "description": "true", 46 | "fetch_retries": "2", 47 | "heading": "npm", 48 | "user": "1000", 49 | "force": "", 50 | "cache_min": "10", 51 | "init_license": "ISC", 52 | "editor": "vi", 53 | "rollback": "true", 54 | "cache_max": "Infinity", 55 | "userconfig": "/home/vagrant/.npmrc", 56 | "engine_strict": "", 57 | "init_author_name": "", 58 | "init_author_url": "", 59 | "tmp": "/tmp", 60 | "depth": "Infinity", 61 | "save_dev": "", 62 | "usage": "", 63 | "cafile": "", 64 | "https_proxy": "", 65 | "onload_script": "", 66 | "rebuild_bundle": "true", 67 | "save_bundle": "", 68 | "shell": "/bin/bash", 69 | "prefix": "/home/vagrant/.nvm/v0.10.36", 70 | "registry": "https://registry.npmjs.org/", 71 | "browser": "", 72 | "cache_lock_wait": "10000", 73 | "save_optional": "", 74 | "searchopts": "", 75 | "versions": "", 76 | "cache": "/home/vagrant/.npm", 77 | "ignore_scripts": "", 78 | "searchsort": "name", 79 | "version": "", 80 | "local_address": "", 81 | "viewer": "man", 82 | "color": "true", 83 | "fetch_retry_mintimeout": "10000", 84 | "umask": "2", 85 | "fetch_retry_maxtimeout": "60000", 86 | "message": "%s", 87 | "ca": "", 88 | "cert": "", 89 | "global": "", 90 | "link": "", 91 | "save": "", 92 | "unicode": "true", 93 | "long": "", 94 | "production": "", 95 | "unsafe_perm": "true", 96 | "node_version": "0.10.36", 97 | "tag": "latest", 98 | "git_tag_version": "true", 99 | "shrinkwrap": "true", 100 | "fetch_retry_factor": "10", 101 | "npat": "", 102 | "proprietary_attribs": "true", 103 | "save_exact": "", 104 | "strict_ssl": "true", 105 | "username": "", 106 | "dev": "", 107 | "globalconfig": "/home/vagrant/.nvm/v0.10.36/etc/npmrc", 108 | "init_module": "/home/vagrant/.npm-init.js", 109 | "parseable": "", 110 | "globalignorefile": "/home/vagrant/.nvm/v0.10.36/etc/npmignore", 111 | "cache_lock_retries": "10", 112 | "save_prefix": "^", 113 | "group": "1000", 114 | "init_author_email": "", 115 | "searchexclude": "", 116 | "git": "git", 117 | "optional": "true", 118 | "email": "", 119 | "json": "", 120 | "spin": "true" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /build-mcrypt/node_modules/mcrypt/build/mcrypt.target.mk: -------------------------------------------------------------------------------- 1 | # This file is generated by gyp; do not edit. 2 | 3 | TOOLSET := target 4 | TARGET := mcrypt 5 | DEFS_Debug := \ 6 | '-D_LARGEFILE_SOURCE' \ 7 | '-D_FILE_OFFSET_BITS=64' \ 8 | '-DBUILDING_NODE_EXTENSION' \ 9 | '-DDEBUG' \ 10 | '-D_DEBUG' 11 | 12 | # Flags passed to all source files. 13 | CFLAGS_Debug := \ 14 | -fPIC \ 15 | -Wall \ 16 | -Wextra \ 17 | -Wno-unused-parameter \ 18 | -pthread \ 19 | -m64 \ 20 | -g \ 21 | -O0 22 | 23 | # Flags passed to only C files. 24 | CFLAGS_C_Debug := 25 | 26 | # Flags passed to only C++ files. 27 | CFLAGS_CC_Debug := \ 28 | -fno-rtti \ 29 | -fno-exceptions 30 | 31 | INCS_Debug := \ 32 | -I/home/vagrant/.node-gyp/0.10.36/src \ 33 | -I/home/vagrant/.node-gyp/0.10.36/deps/uv/include \ 34 | -I/home/vagrant/.node-gyp/0.10.36/deps/v8/include \ 35 | -I/usr/include \ 36 | -I/opt/local/include \ 37 | -I/usr/local/Cellar/mcrypt 38 | 39 | DEFS_Release := \ 40 | '-D_LARGEFILE_SOURCE' \ 41 | '-D_FILE_OFFSET_BITS=64' \ 42 | '-DBUILDING_NODE_EXTENSION' 43 | 44 | # Flags passed to all source files. 45 | CFLAGS_Release := \ 46 | -fPIC \ 47 | -Wall \ 48 | -Wextra \ 49 | -Wno-unused-parameter \ 50 | -pthread \ 51 | -m64 \ 52 | -O2 \ 53 | -fno-strict-aliasing \ 54 | -fno-tree-vrp \ 55 | -fno-tree-sink \ 56 | -fno-omit-frame-pointer 57 | 58 | # Flags passed to only C files. 59 | CFLAGS_C_Release := 60 | 61 | # Flags passed to only C++ files. 62 | CFLAGS_CC_Release := \ 63 | -fno-rtti \ 64 | -fno-exceptions 65 | 66 | INCS_Release := \ 67 | -I/home/vagrant/.node-gyp/0.10.36/src \ 68 | -I/home/vagrant/.node-gyp/0.10.36/deps/uv/include \ 69 | -I/home/vagrant/.node-gyp/0.10.36/deps/v8/include \ 70 | -I/usr/include \ 71 | -I/opt/local/include \ 72 | -I/usr/local/Cellar/mcrypt 73 | 74 | OBJS := \ 75 | $(obj).target/$(TARGET)/src/mcrypt.o 76 | 77 | # Add to the list of files we specially track dependencies for. 78 | all_deps += $(OBJS) 79 | 80 | # CFLAGS et al overrides must be target-local. 81 | # See "Target-specific Variable Values" in the GNU Make manual. 82 | $(OBJS): TOOLSET := $(TOOLSET) 83 | $(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE)) 84 | $(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE)) 85 | 86 | # Suffix rules, putting all outputs into $(obj). 87 | 88 | $(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD 89 | @$(call do_cmd,cxx,1) 90 | 91 | # Try building from generated source, too. 92 | 93 | $(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD 94 | @$(call do_cmd,cxx,1) 95 | 96 | $(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.cc FORCE_DO_CMD 97 | @$(call do_cmd,cxx,1) 98 | 99 | # End of this set of suffix rules 100 | ### Rules for final target. 101 | LDFLAGS_Debug := \ 102 | -pthread \ 103 | -rdynamic \ 104 | -m64 105 | 106 | LDFLAGS_Release := \ 107 | -pthread \ 108 | -rdynamic \ 109 | -m64 110 | 111 | LIBS := \ 112 | -lmcrypt 113 | 114 | $(obj).target/mcrypt.node: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE)) 115 | $(obj).target/mcrypt.node: LIBS := $(LIBS) 116 | $(obj).target/mcrypt.node: TOOLSET := $(TOOLSET) 117 | $(obj).target/mcrypt.node: $(OBJS) FORCE_DO_CMD 118 | $(call do_cmd,solink_module) 119 | 120 | all_deps += $(obj).target/mcrypt.node 121 | # Add target alias 122 | .PHONY: mcrypt 123 | mcrypt: $(builddir)/mcrypt.node 124 | 125 | # Copy this to the executable output path. 126 | $(builddir)/mcrypt.node: TOOLSET := $(TOOLSET) 127 | $(builddir)/mcrypt.node: $(obj).target/mcrypt.node FORCE_DO_CMD 128 | $(call do_cmd,copy) 129 | 130 | all_deps += $(builddir)/mcrypt.node 131 | # Short alias for building this executable. 132 | .PHONY: mcrypt.node 133 | mcrypt.node: $(obj).target/mcrypt.node $(builddir)/mcrypt.node 134 | 135 | # Add executable to "all" target. 136 | .PHONY: all 137 | all: $(builddir)/mcrypt.node 138 | 139 | -------------------------------------------------------------------------------- /build-mcrypt/node_modules/mcrypt/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mcrypt", 3 | "version": "0.0.11", 4 | "description": "MCrypt bindings", 5 | "keywords": [ 6 | "mcrypt", 7 | "crypto" 8 | ], 9 | "homepage": "https://github.com/tugrul/node-mcrypt", 10 | "author": { 11 | "name": "Tuğrul Topuz", 12 | "email": "tugrultopuz@gmail.com" 13 | }, 14 | "bugs": { 15 | "url": "https://github.com/tugrul/node-mcrypt/issues" 16 | }, 17 | "license": "MIT", 18 | "repository": { 19 | "type": "git", 20 | "url": "https://github.com/tugrul/node-mcrypt.git" 21 | }, 22 | "scripts": { 23 | "install": "node-gyp rebuild --release", 24 | "preuninstall": "rm -rf build/*" 25 | }, 26 | "engines": { 27 | "node": ">=0.8.0" 28 | }, 29 | "devDependencies": { 30 | "node-gyp": "*" 31 | }, 32 | "main": "./build/Release/mcrypt", 33 | "gitHead": "d094183f37e712fb1547aa43b0ab89721a8bc095", 34 | "_id": "mcrypt@0.0.11", 35 | "_shasum": "7ebba09ce002343e59615079039655d92e2d9b24", 36 | "_from": "mcrypt@*", 37 | "_npmVersion": "1.4.14", 38 | "_npmUser": { 39 | "name": "tugrul", 40 | "email": "tugrultopuz@gmail.com" 41 | }, 42 | "maintainers": [ 43 | { 44 | "name": "tugrul", 45 | "email": "tugrultopuz@gmail.com" 46 | } 47 | ], 48 | "dist": { 49 | "shasum": "7ebba09ce002343e59615079039655d92e2d9b24", 50 | "tarball": "http://registry.npmjs.org/mcrypt/-/mcrypt-0.0.11.tgz" 51 | }, 52 | "directories": {}, 53 | "_resolved": "https://registry.npmjs.org/mcrypt/-/mcrypt-0.0.11.tgz" 54 | } 55 | -------------------------------------------------------------------------------- /build-mcrypt/node_modules/mcrypt/src/mcrypt.cc: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "mcrypt.h" 4 | 5 | using namespace v8; 6 | 7 | Persistent MCrypt::constructor; 8 | 9 | MCrypt::MCrypt(const Arguments& args): 10 | checkKeySize(true), 11 | checkIvSize(true), 12 | algo(args[0]), 13 | mode(args[1]), 14 | algoDir(args[2]), 15 | modeDir(args[3]) { 16 | 17 | mcrypt_ = mcrypt_module_open(*algo, *algoDir, *mode, *modeDir); 18 | }; 19 | 20 | MCrypt::~MCrypt() { 21 | mcrypt_module_close(mcrypt_); 22 | }; 23 | 24 | template 25 | node::Buffer* MCrypt::transform(const char* plainText, const size_t length, int* result) { 26 | size_t targetLength = length; 27 | 28 | // determine allocation size if the cipher algorithm is block mode 29 | // block mode algorithm needs to fit in modulus of block size 30 | // and it needs to padding space if not fit into block size 31 | if (mcrypt_enc_is_block_algorithm(mcrypt_) == 1) { 32 | size_t blockSize = mcrypt_enc_get_block_size(mcrypt_); 33 | targetLength = (((length - 1) / blockSize) + 1) * blockSize; 34 | } 35 | 36 | char* targetData = new char[targetLength](); 37 | std::copy(plainText, plainText + length, targetData); 38 | 39 | // create a dummy object to return on fail result 40 | node::Buffer* cipherText = node::Buffer::New(1); 41 | 42 | // copy of the key and iv due to mcrypt_generic_init not accepts 43 | // const char for key and iv. direct passing is not safe because 44 | // iv and key could be modified by mcrypt_generic_init in this case 45 | char keyBuf[key.length()]; 46 | key.copy(keyBuf, key.length()); 47 | 48 | char ivBuf[iv.length()]; 49 | iv.copy(ivBuf, iv.length()); 50 | 51 | if ((*result = mcrypt_generic_init(mcrypt_, keyBuf, key.length(), ivBuf)) < 0) { 52 | delete[] targetData; 53 | 54 | return cipherText; 55 | } 56 | 57 | if ((*result = modify(mcrypt_, targetData, targetLength)) != 0) { 58 | delete[] targetData; 59 | 60 | return cipherText; 61 | } 62 | 63 | if ((*result = mcrypt_generic_deinit(mcrypt_)) < 0) { 64 | delete[] targetData; 65 | 66 | return cipherText; 67 | } 68 | 69 | cipherText = node::Buffer::New(targetData, targetLength); 70 | 71 | delete[] targetData; 72 | 73 | return cipherText; 74 | } 75 | 76 | std::vector MCrypt::getKeySizes() { 77 | 78 | int count = 0; 79 | int* sizes = mcrypt_enc_get_supported_key_sizes(mcrypt_, &count); 80 | 81 | if (count <= 0) { 82 | mcrypt_free(sizes); 83 | 84 | size_t size = mcrypt_enc_get_key_size(mcrypt_); 85 | 86 | if (size > 0) { 87 | std::vector keySizes(1); 88 | keySizes[0] = size; 89 | return keySizes; 90 | } 91 | 92 | std::vector keySizes(0); 93 | return keySizes; 94 | } 95 | 96 | std::vector keySizes(count); 97 | 98 | for (int i = 0; i < count; i++) { 99 | keySizes[i] = sizes[i]; 100 | } 101 | 102 | mcrypt_free(sizes); 103 | 104 | return keySizes; 105 | } 106 | 107 | NODE_MCRYPT_METHOD(New) { 108 | HandleScope scope; 109 | 110 | if (!args.IsConstructCall()) { 111 | Local argv[] = {args[0], args[1], args[2], args[3]}; 112 | return scope.Close(constructor->NewInstance(4, argv)); 113 | } 114 | 115 | if (args.Length() < 2) { 116 | return ThrowException(Exception::TypeError(String::New("Missing parameters. Algorithm and mode should be specified."))); 117 | } 118 | 119 | MCrypt* mcrypt = new MCrypt(args); 120 | 121 | MCRYPT_MODULE_ERROR_CHECK(mcrypt) 122 | 123 | mcrypt->Wrap(args.This()); 124 | 125 | return args.This(); 126 | } 127 | 128 | NODE_MCRYPT_METHOD(Open) { 129 | HandleScope scope; 130 | 131 | if (args.Length() < 1) { 132 | return ThrowException(Exception::TypeError(String::New("Missing parameter. Key should be specified."))); 133 | } 134 | 135 | MCrypt* mcrypt = ObjectWrap::Unwrap(args.This()); 136 | 137 | MCRYPT_MODULE_ERROR_CHECK(mcrypt) 138 | 139 | if (args[0]->IsString()) { 140 | String::Utf8Value value(args[0]); 141 | 142 | mcrypt->key = std::string(*value, value.length()); 143 | 144 | } else if (node::Buffer::HasInstance(args[0])) { 145 | 146 | mcrypt->key = std::string(node::Buffer::Data(args[0]), node::Buffer::Length(args[0])); 147 | 148 | } else { 149 | return ThrowException(Exception::TypeError(String::New("Key has got incorrect type. Should be Buffer or String."))); 150 | } 151 | 152 | if (mcrypt->checkKeySize) { 153 | std::vector keySizes = mcrypt->getKeySizes(); 154 | 155 | if (keySizes.size() > 0) { 156 | 157 | bool invalid = true; 158 | 159 | std::stringstream serror; 160 | 161 | serror << "Invalid key size. Available key size are ["; 162 | 163 | for(size_t i = 0; i < keySizes.size(); i++) { 164 | 165 | if (i != 0) { 166 | serror << ", "; 167 | } 168 | 169 | serror << keySizes[i]; 170 | 171 | if (keySizes[i] == mcrypt->key.length()) { 172 | invalid = false; 173 | } 174 | } 175 | 176 | serror << "]"; 177 | 178 | std::string error = serror.str(); 179 | 180 | if (invalid) { 181 | return ThrowException(Exception::TypeError(String::New(error.c_str(), error.length()))); 182 | } 183 | } 184 | } 185 | 186 | if (args[1]->IsUndefined()) { 187 | return scope.Close(Undefined()); 188 | } 189 | 190 | size_t ivLen; 191 | 192 | if (args[1]->IsString()) { 193 | 194 | String::Utf8Value value(args[1]); 195 | 196 | ivLen = value.length(); 197 | mcrypt->iv = std::string(*value, ivLen); 198 | 199 | } else if (node::Buffer::HasInstance(args[1])) { 200 | 201 | ivLen = node::Buffer::Length(args[1]); 202 | mcrypt->iv = std::string(node::Buffer::Data(args[1]), ivLen); 203 | } else { 204 | return ThrowException(Exception::TypeError(String::New("Iv has got incorrect type. Should be Buffer or String."))); 205 | } 206 | 207 | if (mcrypt->checkIvSize) { 208 | if ((size_t)mcrypt_enc_get_iv_size(mcrypt->mcrypt_) != ivLen) { 209 | return ThrowException(Exception::TypeError(String::New("Invalid iv size. You can determine iv size using getIvSize()"))); 210 | } 211 | } 212 | 213 | return scope.Close(Undefined()); 214 | } 215 | 216 | NODE_MCRYPT_METHOD(Encrypt) { 217 | HandleScope scope; 218 | 219 | if (args.Length() < 1) { 220 | return ThrowException(Exception::TypeError(String::New("Missing parameter. Plaintext should be specified."))); 221 | } 222 | 223 | MCrypt* mcrypt = ObjectWrap::Unwrap(args.This()); 224 | 225 | MCRYPT_MODULE_ERROR_CHECK(mcrypt) 226 | 227 | int result = 0; 228 | node::Buffer* cipherText = node::Buffer::New(1); 229 | 230 | if (args[0]->IsString()) { 231 | 232 | String::Utf8Value value(args[0]); 233 | cipherText = mcrypt->transform(*value, value.length(), &result); 234 | 235 | } else if(node::Buffer::HasInstance(args[0])) { 236 | 237 | cipherText = mcrypt->transform(node::Buffer::Data(args[0]), node::Buffer::Length(args[0]), &result); 238 | 239 | } else { 240 | return ThrowException(Exception::TypeError(String::New("Plaintext has got incorrect type. Should be Buffer or String."))); 241 | } 242 | 243 | if (result != 0) { 244 | const char* error = mcrypt_strerror(result); 245 | return ThrowException(Exception::Error(String::New(error))); 246 | } 247 | 248 | return scope.Close(cipherText->handle_); 249 | } 250 | 251 | NODE_MCRYPT_METHOD(Decrypt) { 252 | HandleScope scope; 253 | 254 | if (args.Length() < 1) { 255 | return ThrowException(Exception::TypeError(String::New("Missing parameter. Plaintext should be specified."))); 256 | } 257 | 258 | MCrypt* mcrypt = ObjectWrap::Unwrap(args.This()); 259 | 260 | MCRYPT_MODULE_ERROR_CHECK(mcrypt) 261 | 262 | int result = 0; 263 | node::Buffer* plainText = node::Buffer::New(1); 264 | 265 | if (args[0]->IsString()) { 266 | 267 | String::Utf8Value value(args[0]); 268 | plainText = mcrypt->transform(*value, value.length(), &result); 269 | 270 | } else if (node::Buffer::HasInstance(args[0])) { 271 | 272 | plainText = mcrypt->transform(node::Buffer::Data(args[0]), node::Buffer::Length(args[0]), &result); 273 | 274 | } else { 275 | return ThrowException(Exception::TypeError(String::New("Ciphertext has got incorrect type. Should be Buffer or String."))); 276 | } 277 | 278 | if (result != 0) { 279 | const char* error = mcrypt_strerror(result); 280 | return ThrowException(Exception::Error(String::New(error))); 281 | } 282 | 283 | return scope.Close(plainText->handle_); 284 | } 285 | 286 | NODE_MCRYPT_METHOD(ValidateKeySize) { 287 | HandleScope scope; 288 | 289 | if(args.Length() == 0) { 290 | return scope.Close(Undefined()); 291 | } 292 | 293 | MCrypt* mcrypt = ObjectWrap::Unwrap(args.This()); 294 | Local state = args[0]->ToBoolean(); 295 | mcrypt->checkKeySize = state->Value(); 296 | 297 | return scope.Close(Undefined()); 298 | } 299 | 300 | NODE_MCRYPT_METHOD(ValidateIvSize) { 301 | HandleScope scope; 302 | 303 | if(args.Length() == 0) { 304 | return scope.Close(Undefined()); 305 | } 306 | 307 | MCrypt* mcrypt = ObjectWrap::Unwrap(args.This()); 308 | Local state = args[0]->ToBoolean(); 309 | mcrypt->checkIvSize = state->Value(); 310 | 311 | return scope.Close(Undefined()); 312 | } 313 | 314 | NODE_MCRYPT_METHOD(SelfTest) { 315 | HandleScope scope; 316 | 317 | MCrypt* mcrypt = ObjectWrap::Unwrap(args.This()); 318 | 319 | MCRYPT_MODULE_ERROR_CHECK(mcrypt) 320 | 321 | if (mcrypt_enc_self_test(mcrypt->mcrypt_) == 0) { 322 | return scope.Close(True()); 323 | } 324 | 325 | return scope.Close(False()); 326 | } 327 | 328 | NODE_MCRYPT_METHOD(IsBlockAlgorithmMode) { 329 | HandleScope scope; 330 | 331 | MCrypt* mcrypt = ObjectWrap::Unwrap(args.This()); 332 | 333 | MCRYPT_MODULE_ERROR_CHECK(mcrypt) 334 | 335 | if (mcrypt_enc_is_block_algorithm_mode(mcrypt->mcrypt_) == 1) { 336 | return scope.Close(True()); 337 | } 338 | 339 | return scope.Close(False()); 340 | } 341 | 342 | NODE_MCRYPT_METHOD(IsBlockAlgorithm) { 343 | HandleScope scope; 344 | 345 | MCrypt* mcrypt = ObjectWrap::Unwrap(args.This()); 346 | 347 | MCRYPT_MODULE_ERROR_CHECK(mcrypt) 348 | 349 | if (mcrypt_enc_is_block_algorithm(mcrypt->mcrypt_) == 1) { 350 | return scope.Close(True()); 351 | } 352 | 353 | return scope.Close(False()); 354 | } 355 | 356 | NODE_MCRYPT_METHOD(IsBlockMode) { 357 | HandleScope scope; 358 | 359 | MCrypt* mcrypt = ObjectWrap::Unwrap(args.This()); 360 | 361 | MCRYPT_MODULE_ERROR_CHECK(mcrypt) 362 | 363 | if (mcrypt_enc_is_block_mode(mcrypt->mcrypt_) == 1) { 364 | return scope.Close(True()); 365 | } 366 | 367 | return scope.Close(False()); 368 | } 369 | 370 | NODE_MCRYPT_METHOD(GetBlockSize) { 371 | HandleScope scope; 372 | 373 | MCrypt* mcrypt = ObjectWrap::Unwrap(args.This()); 374 | 375 | MCRYPT_MODULE_ERROR_CHECK(mcrypt) 376 | 377 | int blockSize = mcrypt_enc_get_block_size(mcrypt->mcrypt_); 378 | 379 | return scope.Close(Number::New(blockSize)); 380 | } 381 | 382 | NODE_MCRYPT_METHOD(GetKeySize) { 383 | HandleScope scope; 384 | 385 | MCrypt* mcrypt = ObjectWrap::Unwrap(args.This()); 386 | 387 | MCRYPT_MODULE_ERROR_CHECK(mcrypt) 388 | 389 | int keySize = mcrypt_enc_get_key_size(mcrypt->mcrypt_); 390 | 391 | return scope.Close(Number::New(keySize)); 392 | } 393 | 394 | NODE_MCRYPT_METHOD(GetSupportedKeySizes) { 395 | HandleScope scope; 396 | 397 | MCrypt* mcrypt = ObjectWrap::Unwrap(args.This()); 398 | 399 | MCRYPT_MODULE_ERROR_CHECK(mcrypt) 400 | 401 | std::vector keySizes = mcrypt->getKeySizes(); 402 | 403 | Handle array = Array::New(keySizes.size()); 404 | 405 | for (size_t i = 0; i < keySizes.size(); i++) { 406 | array->Set(i, Number::New(keySizes[i])); 407 | } 408 | 409 | return scope.Close(array); 410 | } 411 | 412 | NODE_MCRYPT_METHOD(GetIvSize) { 413 | HandleScope scope; 414 | 415 | MCrypt* mcrypt = ObjectWrap::Unwrap(args.This()); 416 | 417 | MCRYPT_MODULE_ERROR_CHECK(mcrypt) 418 | 419 | int ivSize = mcrypt_enc_get_iv_size(mcrypt->mcrypt_); 420 | 421 | return scope.Close(Number::New(ivSize)); 422 | } 423 | 424 | NODE_MCRYPT_METHOD(HasIv) { 425 | HandleScope scope; 426 | 427 | MCrypt* mcrypt = ObjectWrap::Unwrap(args.This()); 428 | 429 | MCRYPT_MODULE_ERROR_CHECK(mcrypt) 430 | 431 | if (mcrypt_enc_mode_has_iv(mcrypt->mcrypt_) == 1) { 432 | return scope.Close(True()); 433 | } 434 | 435 | return scope.Close(False()); 436 | } 437 | 438 | NODE_MCRYPT_METHOD(GetAlgorithmName) { 439 | HandleScope scope; 440 | 441 | MCrypt* mcrypt = ObjectWrap::Unwrap(args.This()); 442 | 443 | MCRYPT_MODULE_ERROR_CHECK(mcrypt) 444 | 445 | char* name = mcrypt_enc_get_algorithms_name(mcrypt->mcrypt_); 446 | Handle ret = String::New(name); 447 | mcrypt_free(name); 448 | 449 | return scope.Close(ret); 450 | } 451 | 452 | NODE_MCRYPT_METHOD(GetModeName) { 453 | HandleScope scope; 454 | 455 | MCrypt* mcrypt = ObjectWrap::Unwrap(args.This()); 456 | 457 | MCRYPT_MODULE_ERROR_CHECK(mcrypt) 458 | 459 | char* name = mcrypt_enc_get_modes_name(mcrypt->mcrypt_); 460 | Handle ret = String::New(name); 461 | mcrypt_free(name); 462 | 463 | return scope.Close(ret); 464 | } 465 | 466 | NODE_MCRYPT_METHOD(GenerateIv) { 467 | HandleScope scope; 468 | 469 | MCrypt* mcrypt = ObjectWrap::Unwrap(args.This()); 470 | 471 | MCRYPT_MODULE_ERROR_CHECK(mcrypt) 472 | 473 | int ivSize = mcrypt_enc_get_iv_size(mcrypt->mcrypt_); 474 | 475 | node::Buffer* buffer = node::Buffer::New(ivSize); 476 | 477 | char* iv = node::Buffer::Data(buffer); 478 | 479 | while(ivSize) { 480 | iv[--ivSize] = 255.0 * std::rand() / RAND_MAX; 481 | } 482 | 483 | return scope.Close(buffer->handle_); 484 | } 485 | 486 | NODE_MCRYPT_METHOD(GetAlgorithmNames) { 487 | HandleScope scope; 488 | 489 | String::Utf8Value path(args[0]); 490 | 491 | int size = 0; 492 | char** algos = mcrypt_list_algorithms(*path, &size); 493 | 494 | Handle array = Array::New(size); 495 | 496 | if (array.IsEmpty()) { 497 | return Handle(); 498 | } 499 | 500 | for (int i = 0; i < size; i++) { 501 | array->Set(i, String::New(algos[i])); 502 | } 503 | 504 | mcrypt_free_p(algos, size); 505 | 506 | return scope.Close(array); 507 | } 508 | 509 | NODE_MCRYPT_METHOD(GetModeNames) { 510 | HandleScope scope; 511 | 512 | String::Utf8Value path(args[0]); 513 | 514 | int size = 0; 515 | char** modes = mcrypt_list_modes(*path, &size); 516 | 517 | Handle array = Array::New(size); 518 | 519 | if (array.IsEmpty()) 520 | return Handle(); 521 | 522 | for (int i = 0; i < size; i++) { 523 | array->Set(i, String::New(modes[i])); 524 | } 525 | 526 | mcrypt_free_p(modes, size); 527 | 528 | return scope.Close(array); 529 | } 530 | 531 | void MCrypt::Init(Handle exports) { 532 | Local tpl = FunctionTemplate::New(New); 533 | tpl->SetClassName(String::NewSymbol("MCrypt")); 534 | tpl->InstanceTemplate()->SetInternalFieldCount(1); 535 | 536 | Local prototype = tpl->PrototypeTemplate(); 537 | 538 | // prototype 539 | prototype->Set(String::NewSymbol("encrypt"), FunctionTemplate::New(Encrypt)->GetFunction()); 540 | prototype->Set(String::NewSymbol("decrypt"), FunctionTemplate::New(Decrypt)->GetFunction()); 541 | prototype->Set(String::NewSymbol("open"), FunctionTemplate::New(Open)->GetFunction()); 542 | prototype->Set(String::NewSymbol("validateKeySize"), FunctionTemplate::New(ValidateKeySize)->GetFunction()); 543 | prototype->Set(String::NewSymbol("validateIvSize"), FunctionTemplate::New(ValidateIvSize)->GetFunction()); 544 | prototype->Set(String::NewSymbol("selfTest"), FunctionTemplate::New(SelfTest)->GetFunction()); 545 | prototype->Set(String::NewSymbol("isBlockAlgorithmMode"), FunctionTemplate::New(IsBlockAlgorithmMode)->GetFunction()); 546 | prototype->Set(String::NewSymbol("isBlockAlgorithm"), FunctionTemplate::New(IsBlockAlgorithm)->GetFunction()); 547 | prototype->Set(String::NewSymbol("isBlockMode"), FunctionTemplate::New(IsBlockMode)->GetFunction()); 548 | prototype->Set(String::NewSymbol("getBlockSize"), FunctionTemplate::New(GetBlockSize)->GetFunction()); 549 | prototype->Set(String::NewSymbol("getKeySize"), FunctionTemplate::New(GetKeySize)->GetFunction()); 550 | prototype->Set(String::NewSymbol("getSupportedKeySizes"), FunctionTemplate::New(GetSupportedKeySizes)->GetFunction()); 551 | prototype->Set(String::NewSymbol("getIvSize"), FunctionTemplate::New(GetIvSize)->GetFunction()); 552 | prototype->Set(String::NewSymbol("hasIv"), FunctionTemplate::New(HasIv)->GetFunction()); 553 | prototype->Set(String::NewSymbol("getAlgorithmName"), FunctionTemplate::New(GetAlgorithmName)->GetFunction()); 554 | prototype->Set(String::NewSymbol("getModeName"), FunctionTemplate::New(GetModeName)->GetFunction()); 555 | prototype->Set(String::NewSymbol("generateIv"), FunctionTemplate::New(GenerateIv)->GetFunction()); 556 | 557 | // exports 558 | constructor = Persistent::New(tpl->GetFunction()); 559 | exports->Set(String::NewSymbol("MCrypt"), constructor); 560 | exports->Set(String::NewSymbol("getAlgorithmNames"), FunctionTemplate::New(GetAlgorithmNames)->GetFunction()); 561 | exports->Set(String::NewSymbol("getModeNames"), FunctionTemplate::New(GetModeNames)->GetFunction()); 562 | } 563 | 564 | NODE_MODULE(mcrypt, MCrypt::Init) 565 | -------------------------------------------------------------------------------- /build-mcrypt/node_modules/mcrypt/src/mcrypt.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef SRC_NODE_MCRYPT_H_ 3 | #define SRC_NODE_MCRYPT_H_ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #define MCRYPT_MODULE_ERROR_CHECK(mcrypt) if (mcrypt->mcrypt_ == MCRYPT_FAILED) { \ 14 | return ThrowException(Exception::ReferenceError(String::New("MCrypt module could not open"))); \ 15 | } 16 | 17 | #define NODE_MCRYPT_METHOD_PROTO(MethodName) static Handle MethodName(const Arguments& args) 18 | #define NODE_MCRYPT_METHOD(MethodName) Handle MCrypt::MethodName(const Arguments& args) 19 | 20 | using namespace v8; 21 | 22 | class MCrypt : public node::ObjectWrap { 23 | public: 24 | static void Init(Handle exports); 25 | 26 | private: 27 | MCrypt(const Arguments& args); 28 | ~MCrypt(); 29 | 30 | template 31 | node::Buffer* transform(const char* plainText, const size_t length, int* result); 32 | 33 | std::vector getKeySizes(); 34 | 35 | static Persistent constructor; 36 | 37 | NODE_MCRYPT_METHOD_PROTO(New); 38 | NODE_MCRYPT_METHOD_PROTO(Encrypt); 39 | NODE_MCRYPT_METHOD_PROTO(Decrypt); 40 | NODE_MCRYPT_METHOD_PROTO(Open); 41 | NODE_MCRYPT_METHOD_PROTO(ValidateKeySize); 42 | NODE_MCRYPT_METHOD_PROTO(ValidateIvSize); 43 | NODE_MCRYPT_METHOD_PROTO(SelfTest); 44 | NODE_MCRYPT_METHOD_PROTO(IsBlockAlgorithmMode); 45 | NODE_MCRYPT_METHOD_PROTO(IsBlockAlgorithm); 46 | NODE_MCRYPT_METHOD_PROTO(IsBlockMode); 47 | NODE_MCRYPT_METHOD_PROTO(GetBlockSize); 48 | NODE_MCRYPT_METHOD_PROTO(GetKeySize); 49 | NODE_MCRYPT_METHOD_PROTO(GetSupportedKeySizes); 50 | NODE_MCRYPT_METHOD_PROTO(GetIvSize); 51 | NODE_MCRYPT_METHOD_PROTO(HasIv); 52 | NODE_MCRYPT_METHOD_PROTO(GetAlgorithmName); 53 | NODE_MCRYPT_METHOD_PROTO(GetModeName); 54 | NODE_MCRYPT_METHOD_PROTO(GenerateIv); 55 | NODE_MCRYPT_METHOD_PROTO(Close); 56 | 57 | NODE_MCRYPT_METHOD_PROTO(GetAlgorithmNames); 58 | NODE_MCRYPT_METHOD_PROTO(GetModeNames); 59 | 60 | MCRYPT mcrypt_; 61 | std::string key; 62 | std::string iv; 63 | 64 | bool checkKeySize; 65 | bool checkIvSize; 66 | 67 | String::AsciiValue algo; 68 | String::AsciiValue mode; 69 | String::AsciiValue algoDir; 70 | String::AsciiValue modeDir; 71 | }; 72 | 73 | #endif // ~ SRC_NODE_MCRYPT_H_ 74 | -------------------------------------------------------------------------------- /build-mcrypt/node_modules/mcrypt/test.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | var MCrypt = require('./build/Debug/mcrypt.node').MCrypt; 4 | 5 | var rijndael = new MCrypt('rijndael-128', 'cbc'); 6 | rijndael.open('aaaabbbbccccdddd'); 7 | 8 | // 0.0.7 output: 9 | // 8cc419b7cb0f744dbada17858ea84d00 10 | // Correct! equals with php mcrypt module 11 | // but 0.0.10 output: 12 | // b2af83d35ab9b920bcdbb3ae1425f454 13 | console.log(rijndael.encrypt('123456').toString('hex')); 14 | 15 | 16 | -------------------------------------------------------------------------------- /build-mcrypt/node_modules/mcrypt/test/test.js: -------------------------------------------------------------------------------- 1 | 2 | var mcrypt = require('../build/Release/mcrypt'); 3 | var assert = require('assert'); 4 | 5 | describe('MCrypt', function() { 6 | 7 | describe('getAlgorithmNames', function() { 8 | it('should be a function', function() { 9 | assert(typeof mcrypt.getAlgorithmNames == 'function', 'there is getAlgorithmNames function'); 10 | }); 11 | 12 | it('should return an array', function() { 13 | assert(mcrypt.getAlgorithmNames() instanceof Array, 'there is an array'); 14 | }); 15 | 16 | it('should some values in the array', function() { 17 | assert(mcrypt.getAlgorithmNames().length > 0, 'there are some values'); 18 | }); 19 | 20 | it('should be DES value in the array', function() { 21 | assert(mcrypt.getAlgorithmNames().indexOf('des') > -1, 'there is the des value'); 22 | }); 23 | }); 24 | 25 | describe('getModeNames', function(){ 26 | it('should be a function', function() { 27 | assert(typeof mcrypt.getModeNames == 'function', 'there is getModeNames function'); 28 | }); 29 | 30 | it('should return an array', function() { 31 | assert(mcrypt.getModeNames() instanceof Array, 'there is an array'); 32 | }); 33 | 34 | it('should some values in the array', function() { 35 | assert(mcrypt.getModeNames().length > 0, 'there are some values'); 36 | }); 37 | 38 | it('should be ECB value in the array', function() { 39 | assert(mcrypt.getModeNames().indexOf('ecb') > -1, 'there is the ecb value'); 40 | }); 41 | }); 42 | 43 | 44 | describe('constructor', function() { 45 | it('should be a constructor function', function() { 46 | assert(typeof mcrypt.MCrypt == 'function', 'there is MCrypt constructor function'); 47 | }); 48 | 49 | it('should throw exception without parameters', function() { 50 | assert.throws(function(){ 51 | new mcrypt.MCrypt(); // without algo and mode 52 | }, TypeError, 'there is a TypeError when parameters are missed'); 53 | }); 54 | 55 | it('should throw exception with less parameter', function(){ 56 | assert.throws(function(){ 57 | new mcrypt.MCrypt('des'); // without mode 58 | }); 59 | }); 60 | 61 | it('should throw exception with wrong parameters', function() { 62 | assert.throws(function(){ 63 | new mcrypt.MCrypt('deso', 'ecb'); // invalid algo name 64 | }, ReferenceError, 'there is a ReferenceError when parameters are wrong'); 65 | 66 | assert.throws(function(){ 67 | new mcrypt.MCrypt('des', 'ebo'); // invalid mode name 68 | }, ReferenceError, 'there is a ReferenceError when parameters are wrong'); 69 | }); 70 | 71 | it('should not throw exception with correct parameters', function() { 72 | assert.doesNotThrow(function() { 73 | new mcrypt.MCrypt('des', 'ecb'); 74 | }, 'there is no error when parameters are correct'); 75 | }); 76 | }); 77 | 78 | describe('MCrypt instance (BLOWFISH-ECB)', function() { 79 | var mc = new mcrypt.MCrypt('blowfish', 'ecb'); 80 | 81 | it('should be an object', function() { 82 | assert(typeof mc == 'object', 'there is an object'); 83 | }); 84 | 85 | describe('open', function() { 86 | var key = 'typeconfig.sys^_-'; 87 | 88 | it('should open without error', function() { 89 | assert.doesNotThrow(function() { 90 | mc.validateKeySize(false); 91 | mc.open(key); 92 | }, 'there is error when opened with key'); 93 | }); 94 | }); 95 | }); 96 | 97 | describe('MCrypt instance (DES-ECB)', function() { 98 | var mc = new mcrypt.MCrypt('des', 'ecb'); 99 | 100 | it('should be an object', function() { 101 | assert(typeof mc == "object", 'there is an object'); 102 | }); 103 | 104 | describe('open', function() { 105 | var key = 'madepass'; 106 | var plaintext = 'top secret information!!'; 107 | var ciphertext = '7Bg68sriLJuKCYPl1NmSwGrBrE0E5I+T'; 108 | 109 | it('should open without error', function(){ 110 | assert.doesNotThrow(function(){ 111 | mc.open(key); 112 | }, 'there is error when opened with key'); 113 | }); 114 | 115 | describe('encrypt', function() { 116 | it('plaintext and decrypted ciphertext should be same', function(){ 117 | assert.equal(ciphertext, mc.encrypt(plaintext).toString('base64'), 'ciphertext are not same'); 118 | }); 119 | 120 | }); 121 | 122 | describe('decrypt', function() { 123 | it('ciphertext and encrypted plaintext should be same', function(){ 124 | assert.equal(plaintext, mc.decrypt(new Buffer(ciphertext, 'base64')).toString(), 'plaintext are not same'); 125 | }); 126 | }); 127 | 128 | describe('selfTest', function(){ 129 | it('should return true', function(){ 130 | assert(mc.selfTest(), 'return value is not true'); 131 | }); 132 | }); 133 | 134 | describe('isBlockAlgorithmMode', function(){ 135 | it('should return true', function(){ 136 | assert(mc.isBlockAlgorithmMode(), 'return value is not true'); 137 | }); 138 | }); 139 | 140 | describe('isBlockAlgorithm', function(){ 141 | it('should return true', function(){ 142 | assert(mc.isBlockAlgorithm(), 'return value is not true'); 143 | }); 144 | }); 145 | 146 | describe('isBlockMode', function(){ 147 | it('should return true', function(){ 148 | assert(mc.isBlockMode(), 'return value is not true'); 149 | }); 150 | }); 151 | 152 | describe('getKeySize', function(){ 153 | it('should equal to keysize of algorithm', function(){ 154 | assert.equal(mc.getKeySize(), 8, 'return value is not 8'); 155 | }); 156 | }); 157 | 158 | describe('getSupportedKeySizes', function(){ 159 | it('should return an array', function() { 160 | assert(mc.getSupportedKeySizes() instanceof Array, 'return value is not array'); 161 | }); 162 | 163 | it('array should not be empty', function() { 164 | assert(mc.getSupportedKeySizes().length > 0, 'return value is empty'); 165 | }); 166 | }); 167 | 168 | describe('getIvSize', function(){ 169 | it('should equal to iv size of algorithm', function(){ 170 | assert.equal(mc.getIvSize(), 8, 'iv size not equals with 8'); 171 | }); 172 | }); 173 | 174 | describe('hasIv', function(){ 175 | it('should return false', function(){ 176 | assert.equal(mc.hasIv(), false, 'return value is not false'); 177 | }); 178 | }); 179 | 180 | describe('getAlgorithmName', function(){ 181 | it('should return DES', function(){ 182 | assert.equal(mc.getAlgorithmName(), 'DES', 'return value is not DES'); 183 | }); 184 | }); 185 | 186 | describe('getModeName', function() { 187 | it('should return ECB', function(){ 188 | assert.equal(mc.getModeName(), 'ECB', 'return value is not ECB'); 189 | }); 190 | }); 191 | 192 | }); 193 | 194 | 195 | }); 196 | }); 197 | 198 | -------------------------------------------------------------------------------- /build-mcrypt/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodejs-mcrypt-example", 3 | "version": "0.0.1", 4 | "description": "nodejs mcrypt example", 5 | "scripts": { 6 | "start": "node index.js" 7 | }, 8 | "dependencies": { 9 | "mcrypt": "*" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /build-nginx/Dockerfile-daemon-off: -------------------------------------------------------------------------------- 1 | FROM nginx:1.9.0 2 | 3 | # start Nginx server, without daemonize itself (correct!) 4 | CMD [ "nginx", "-g", "daemon off;" ] 5 | -------------------------------------------------------------------------------- /build-nginx/Dockerfile-daemonize: -------------------------------------------------------------------------------- 1 | FROM nginx:1.9.0 2 | 3 | # start Nginx server, and daemonize itself (incorrect!) 4 | CMD [ "nginx" ] 5 | -------------------------------------------------------------------------------- /build-nginx/Dockerfile.official-1.9.0: -------------------------------------------------------------------------------- 1 | FROM debian:jessie 2 | 3 | MAINTAINER NGINX Docker Maintainers "docker-maint@nginx.com" 4 | 5 | RUN apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys 573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62 6 | RUN echo "deb http://nginx.org/packages/mainline/debian/ jessie nginx" >> /etc/apt/sources.list 7 | 8 | ENV NGINX_VERSION 1.9.0-1~jessie 9 | 10 | RUN apt-get update && \ 11 | apt-get install -y ca-certificates nginx=${NGINX_VERSION} && \ 12 | rm -rf /var/lib/apt/lists/* 13 | 14 | # forward request and error logs to docker log collector 15 | RUN ln -sf /dev/stdout /var/log/nginx/access.log 16 | RUN ln -sf /dev/stderr /var/log/nginx/error.log 17 | 18 | VOLUME ["/var/cache/nginx"] 19 | 20 | EXPOSE 80 443 21 | 22 | CMD ["nginx", "-g", "daemon off;"] 23 | -------------------------------------------------------------------------------- /build-nginx/README.md: -------------------------------------------------------------------------------- 1 | Build a derived Nginx image for Ubuntu 14.04 LTS (Trusty) 2 | === 3 | 4 | 5 | ## Purpose 6 | 7 | - Demostrate how to build derived Nginx image(s) from Dockerfile(s). 8 | 9 | - Demostrate different behaviors while running Nginx with/without the "daemon off" flag. 10 | 11 | 12 | ## Build a (correct!) daemon-off Nginx image 13 | 14 | - Docker 1.5.0 or higher: 15 | 16 | ``` 17 | $ docker build -f Dockerfile-daemon-off . 18 | ``` 19 | 20 | - Docker 1.4.1 or lower: 21 | 22 | ``` 23 | $ cp Dockerfile-daemon-off Dockerfile 24 | $ docker build . 25 | ``` 26 | 27 | ## Build an (incorrect!) daemonize Nginx image 28 | 29 | - Docker 1.5.0 or higher: 30 | 31 | ``` 32 | $ docker build -f Dockerfile-daemonize . 33 | ``` 34 | 35 | - Docker 1.4.1 or lower: 36 | 37 | ``` 38 | $ cp Dockerfile-daemonize Dockerfile 39 | $ docker build . 40 | ``` 41 | -------------------------------------------------------------------------------- /build-nginx/docker-compose.yml: -------------------------------------------------------------------------------- 1 | nginx: 2 | image: nginx:1.9.0 3 | ports: 4 | - "10081:80" 5 | volumes: 6 | - .:/usr/share/nginx/html:ro 7 | 8 | -------------------------------------------------------------------------------- /build-redis-el5/Dockerfile: -------------------------------------------------------------------------------- 1 | # a naive Redis image 2 | 3 | FROM centos:5.11 4 | 5 | # copy to image/container 6 | COPY redis-2.8.19-1.el5.remi.x86_64.rpm redis-server.rpm 7 | COPY jemalloc-3.6.0-2.el5.x86_64.rpm jemalloc.rpm 8 | 9 | # install from RPM 10 | RUN rpm -i jemalloc.rpm redis-server.rpm 11 | 12 | # start Redis server 13 | CMD [ "redis-server" ] 14 | -------------------------------------------------------------------------------- /build-redis-el5/README.md: -------------------------------------------------------------------------------- 1 | Build a naive Redis image for CentOS 5 2 | === 3 | 4 | 5 | ## Purpose 6 | 7 | Demostrate how to build a naive Redis image from Dockerfile. 8 | 9 | This lab uses a pre-downloaded RPM file to minimize time to completion. Alternatives have drawbacks for this lab: 10 | 11 | - Building from tarball source will require `gcc`, `make` and other dependencies. 12 | - Installing by `yum` will require downloading packages on-the-fly. 13 | 14 | It is just a naive demo, especially in early workshop stages. For a better Dockerfile to learn from, see [official repo](https://registry.hub.docker.com/_/redis/). 15 | 16 | 17 | ## Package 18 | 19 | Redis: 20 | 21 | - Rpmfind: [`remi`](http://www.rpmfind.net/linux/rpm2html/search.php?query=redis) 22 | 23 | - RPM file: [redis-2.8.19-1.el5.remi.x86_64.rpm](http://www.rpmfind.net//linux/RPM/remi/enterprise/5/x86_64/redis-2.8.19-1.el5.remi.x86_64.html) 24 | 25 | jemalloc: 26 | 27 | - Rpmfind: [`EPEL`](http://www.rpmfind.net/linux/rpm2html/search.php?query=libjemalloc.so.1%28%29%2864bit%29) 28 | 29 | - RPM file: [jemalloc-3.6.0-2.el5.x86_64.rpm](http://www.rpmfind.net//linux/RPM/epel/5/x86_64/jemalloc-3.6.0-2.el5.x86_64.html) 30 | 31 | -------------------------------------------------------------------------------- /build-redis-el5/jemalloc-3.6.0-2.el5.x86_64.rpm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/William-Yeh/docker-workshop/88c1d4b0674c3e1d2c2d6c3e2c02d406bcf6e791/build-redis-el5/jemalloc-3.6.0-2.el5.x86_64.rpm -------------------------------------------------------------------------------- /build-redis-el5/redis-2.8.19-1.el5.remi.x86_64.rpm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/William-Yeh/docker-workshop/88c1d4b0674c3e1d2c2d6c3e2c02d406bcf6e791/build-redis-el5/redis-2.8.19-1.el5.remi.x86_64.rpm -------------------------------------------------------------------------------- /build-redis-linking/Dockerfile: -------------------------------------------------------------------------------- 1 | # a naive Redis image 2 | 3 | FROM ubuntu:14.04 4 | 5 | # copy to image/container 6 | COPY redis-server_2.8.19.deb redis-server.deb 7 | 8 | # install from deb 9 | RUN dpkg -i redis-server.deb 10 | 11 | 12 | # expose Redis port (used by "redis-server") 13 | EXPOSE 6379 14 | 15 | # install wrapper scripts 16 | COPY client /usr/local/bin/ 17 | COPY benchmark /usr/local/bin/ 18 | 19 | 20 | # start Redis server 21 | CMD [ "redis-server" ] 22 | -------------------------------------------------------------------------------- /build-redis-linking/Dockerfile.official-2.8.19: -------------------------------------------------------------------------------- 1 | FROM debian:wheezy 2 | 3 | # add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added 4 | RUN groupadd -r redis && useradd -r -g redis redis 5 | 6 | RUN apt-get update \ 7 | && apt-get install -y curl \ 8 | && rm -rf /var/lib/apt/lists/* 9 | 10 | # grab gosu for easy step-down from root 11 | RUN gpg --keyserver pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 12 | RUN curl -o /usr/local/bin/gosu -SL "https://github.com/tianon/gosu/releases/download/1.2/gosu-$(dpkg --print-architecture)" \ 13 | && curl -o /usr/local/bin/gosu.asc -SL "https://github.com/tianon/gosu/releases/download/1.2/gosu-$(dpkg --print-architecture).asc" \ 14 | && gpg --verify /usr/local/bin/gosu.asc \ 15 | && rm /usr/local/bin/gosu.asc \ 16 | && chmod +x /usr/local/bin/gosu 17 | 18 | ENV REDIS_VERSION 2.8.19 19 | ENV REDIS_DOWNLOAD_URL http://download.redis.io/releases/redis-2.8.19.tar.gz 20 | ENV REDIS_DOWNLOAD_SHA1 3e362f4770ac2fdbdce58a5aa951c1967e0facc8 21 | 22 | # for redis-sentinel see: http://redis.io/topics/sentinel 23 | RUN buildDeps='gcc libc6-dev make'; \ 24 | set -x \ 25 | && apt-get update && apt-get install -y $buildDeps --no-install-recommends \ 26 | && rm -rf /var/lib/apt/lists/* \ 27 | && mkdir -p /usr/src/redis \ 28 | && curl -sSL "$REDIS_DOWNLOAD_URL" -o redis.tar.gz \ 29 | && echo "$REDIS_DOWNLOAD_SHA1 *redis.tar.gz" | sha1sum -c - \ 30 | && tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \ 31 | && rm redis.tar.gz \ 32 | && make -C /usr/src/redis \ 33 | && make -C /usr/src/redis install \ 34 | && rm -r /usr/src/redis \ 35 | && apt-get purge -y --auto-remove $buildDeps 36 | 37 | RUN mkdir /data && chown redis:redis /data 38 | VOLUME /data 39 | WORKDIR /data 40 | 41 | COPY docker-entrypoint.sh /entrypoint.sh 42 | ENTRYPOINT ["/entrypoint.sh"] 43 | 44 | EXPOSE 6379 45 | CMD [ "redis-server" ] 46 | -------------------------------------------------------------------------------- /build-redis-linking/README.md: -------------------------------------------------------------------------------- 1 | Build a naive Redis image (and some wrappers) for Ubuntu 14.04 LTS (Trusty) 2 | === 3 | 4 | 5 | ## Purpose 6 | 7 | Demostrate how to build a naive Redis image (and some wrappers) from Dockerfile. 8 | 9 | This lab uses a pre-downloaded DEB file to minimize time to completion. Alternatives have drawbacks for this lab: 10 | 11 | - Building from tarball source will require `build-essential`. 12 | - Installing by `apt-get` will require downloading packages on-the-fly. 13 | 14 | It is just a naive demo, especially in early workshop stages. For a better Dockerfile to learn from, take [williamyeh/redis](https://registry.hub.docker.com/u/williamyeh/redis/) as a starting point. 15 | 16 | 17 | ## Package 18 | 19 | PPA: [`ppa:rwky/redis`](https://launchpad.net/~rwky/+archive/ubuntu/redis) 20 | 21 | DEB file: [2:2.8.19-rwky1~trusty](https://launchpad.net/~rwky/+archive/ubuntu/redis/+files/redis-server_2.8.19-rwky1~trusty_amd64.deb) 22 | 23 | -------------------------------------------------------------------------------- /build-redis-linking/benchmark: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # A simple wrapper for Dockerized redis-benchmark. 4 | # 5 | # Expecting link alias to be 'redis'. 6 | # 7 | 8 | 9 | exec redis-benchmark -h redis -p 6379 "$@" 10 | #exec redis-benchmark -h $REDIS_PORT_6379_TCP_ADDR -p $REDIS_PORT_6379_TCP_PORT "$@" 11 | -------------------------------------------------------------------------------- /build-redis-linking/client: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # A simple wrapper for Dockerized redis-cli. 4 | # 5 | # Expecting link alias to be 'redis'. 6 | # 7 | 8 | 9 | exec redis-cli -h redis -p 6379 "$@" 10 | #exec redis-cli -h $REDIS_PORT_6379_TCP_ADDR -p $REDIS_PORT_6379_TCP_PORT "$@" 11 | -------------------------------------------------------------------------------- /build-redis-linking/docker-compose-mixed.yml: -------------------------------------------------------------------------------- 1 | benchmark1: 2 | build: . 3 | command: benchmark 4 | links: 5 | - redis1:redis 6 | 7 | benchmark2: 8 | build: . 9 | command: benchmark 10 | links: 11 | - redis2:redis 12 | 13 | redis1: 14 | image: redis:2.8.19 15 | 16 | redis2: 17 | build: . 18 | -------------------------------------------------------------------------------- /build-redis-linking/docker-compose.yml: -------------------------------------------------------------------------------- 1 | benchmark: 2 | build: . 3 | command: benchmark 4 | links: 5 | - redis 6 | 7 | redis: 8 | image: redis:2.8.19 9 | -------------------------------------------------------------------------------- /build-redis-linking/redis-server_2.8.19.deb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/William-Yeh/docker-workshop/88c1d4b0674c3e1d2c2d6c3e2c02d406bcf6e791/build-redis-linking/redis-server_2.8.19.deb -------------------------------------------------------------------------------- /build-redis-mini/.dockerignore: -------------------------------------------------------------------------------- 1 | src 2 | -------------------------------------------------------------------------------- /build-redis-mini/Dockerfile: -------------------------------------------------------------------------------- 1 | # a minimal Dockerized `redis-server` 2 | 3 | FROM scratch 4 | 5 | ADD rootfs.tar.gz / 6 | COPY redis.conf /etc/redis/redis.conf 7 | 8 | # Redis port. 9 | EXPOSE 6379 10 | 11 | 12 | CMD ["redis-server"] 13 | -------------------------------------------------------------------------------- /build-redis-mini/rootfs.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/William-Yeh/docker-workshop/88c1d4b0674c3e1d2c2d6c3e2c02d406bcf6e791/build-redis-mini/rootfs.tar.gz -------------------------------------------------------------------------------- /build-redis-mini/src/build-rootfs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | REDIS_VERSION=3.0.0 4 | 5 | echo "==> Install curl and helper tools..." 6 | sudo apt-get install -y curl make gcc 7 | 8 | 9 | echo "==> Compile..." 10 | tar zxvf redis-$REDIS_VERSION.tar.gz 11 | cd redis-$REDIS_VERSION 12 | make 13 | 14 | 15 | echo "==> Copy aux files..." 16 | cp redis.conf .. 17 | 18 | 19 | echo "==> Clear screen..." 20 | cd .. 21 | clear 22 | 23 | 24 | echo "==> Investigate required .so files..." 25 | ldd redis-$REDIS_VERSION/src/redis-server 26 | 27 | 28 | echo "==> Extract .so files and pack them into rootfs.tar.gz..." 29 | ../extract-elf-so_static_linux-amd64 \ 30 | -z \ 31 | redis-$REDIS_VERSION/src/redis-server 32 | -------------------------------------------------------------------------------- /build-redis-mini/src/clean.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | REDIS_VERSION=3.0.0 4 | 5 | rm -rf redis-$REDIS_VERSION redis.conf rootfs.tar.gz 6 | -------------------------------------------------------------------------------- /build-redis-mini/src/redis-3.0.0.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/William-Yeh/docker-workshop/88c1d4b0674c3e1d2c2d6c3e2c02d406bcf6e791/build-redis-mini/src/redis-3.0.0.tar.gz -------------------------------------------------------------------------------- /build-redis/Dockerfile: -------------------------------------------------------------------------------- 1 | # a naive Redis image 2 | 3 | FROM ubuntu:14.04 4 | 5 | # copy to image/container 6 | COPY redis-server_2.8.19.deb redis-server.deb 7 | 8 | # install from deb 9 | RUN dpkg -i redis-server.deb 10 | 11 | # start Redis server 12 | CMD [ "redis-server" ] 13 | -------------------------------------------------------------------------------- /build-redis/Dockerfile.official-2.8.19: -------------------------------------------------------------------------------- 1 | FROM debian:wheezy 2 | 3 | # add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added 4 | RUN groupadd -r redis && useradd -r -g redis redis 5 | 6 | RUN apt-get update \ 7 | && apt-get install -y curl \ 8 | && rm -rf /var/lib/apt/lists/* 9 | 10 | # grab gosu for easy step-down from root 11 | RUN gpg --keyserver pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 12 | RUN curl -o /usr/local/bin/gosu -SL "https://github.com/tianon/gosu/releases/download/1.2/gosu-$(dpkg --print-architecture)" \ 13 | && curl -o /usr/local/bin/gosu.asc -SL "https://github.com/tianon/gosu/releases/download/1.2/gosu-$(dpkg --print-architecture).asc" \ 14 | && gpg --verify /usr/local/bin/gosu.asc \ 15 | && rm /usr/local/bin/gosu.asc \ 16 | && chmod +x /usr/local/bin/gosu 17 | 18 | ENV REDIS_VERSION 2.8.19 19 | ENV REDIS_DOWNLOAD_URL http://download.redis.io/releases/redis-2.8.19.tar.gz 20 | ENV REDIS_DOWNLOAD_SHA1 3e362f4770ac2fdbdce58a5aa951c1967e0facc8 21 | 22 | # for redis-sentinel see: http://redis.io/topics/sentinel 23 | RUN buildDeps='gcc libc6-dev make'; \ 24 | set -x \ 25 | && apt-get update && apt-get install -y $buildDeps --no-install-recommends \ 26 | && rm -rf /var/lib/apt/lists/* \ 27 | && mkdir -p /usr/src/redis \ 28 | && curl -sSL "$REDIS_DOWNLOAD_URL" -o redis.tar.gz \ 29 | && echo "$REDIS_DOWNLOAD_SHA1 *redis.tar.gz" | sha1sum -c - \ 30 | && tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \ 31 | && rm redis.tar.gz \ 32 | && make -C /usr/src/redis \ 33 | && make -C /usr/src/redis install \ 34 | && rm -r /usr/src/redis \ 35 | && apt-get purge -y --auto-remove $buildDeps 36 | 37 | RUN mkdir /data && chown redis:redis /data 38 | VOLUME /data 39 | WORKDIR /data 40 | 41 | COPY docker-entrypoint.sh /entrypoint.sh 42 | ENTRYPOINT ["/entrypoint.sh"] 43 | 44 | EXPOSE 6379 45 | CMD [ "redis-server" ] 46 | -------------------------------------------------------------------------------- /build-redis/README.md: -------------------------------------------------------------------------------- 1 | Build a naive Redis image for Ubuntu 14.04 LTS (Trusty) 2 | === 3 | 4 | 5 | ## Purpose 6 | 7 | Demostrate how to build a naive Redis image from Dockerfile. 8 | 9 | This lab uses a pre-downloaded DEB file to minimize time to completion. Alternatives have drawbacks for this lab: 10 | 11 | - Building from tarball source will require `build-essential`. 12 | - Installing by `apt-get` will require downloading packages on-the-fly. 13 | 14 | It is just a naive demo, especially in early workshop stages. For a better Dockerfile to learn from, see [official repo](https://registry.hub.docker.com/_/redis/). 15 | 16 | 17 | ## Package 18 | 19 | PPA: [`ppa:rwky/redis`](https://launchpad.net/~rwky/+archive/ubuntu/redis) 20 | 21 | DEB file: [2:2.8.19-rwky1~trusty](https://launchpad.net/~rwky/+archive/ubuntu/redis/+files/redis-server_2.8.19-rwky1~trusty_amd64.deb) 22 | 23 | -------------------------------------------------------------------------------- /build-redis/redis-server_2.8.19.deb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/William-Yeh/docker-workshop/88c1d4b0674c3e1d2c2d6c3e2c02d406bcf6e791/build-redis/redis-server_2.8.19.deb -------------------------------------------------------------------------------- /build-walk/README.md: -------------------------------------------------------------------------------- 1 | Several walk-tree examples 2 | === 3 | 4 | This directory demonstrates several Docker topics: 5 | 6 | - Minimal Docker images (all less than 3 MB). 7 | 8 | - Rootfs concept inside the Docker images/containers. 9 | 10 | - Dependencies on runtime components (e.g., `.so` files). 11 | 12 | - Isolation of resources. 13 | 14 | 15 | ## Main programs 16 | 17 | The program “**walk**” tries to traverse directory structures starting from specified path (`.` by default). For brevity, it excludes `/dev`, `/proc`, and `/sys` directories from the output. 18 | 19 | 20 | Two compiled versions of the same functionality written in C are provided: 21 | 22 | 1. Static version `walk-static`: a fully statically-linked ELF executable (i.e., without runtime dependencies on any `.so` files). 23 | 24 | 25 | 2. Dynamic version `walk-dynamic`: an ordinary ELF executabie with runtime dependencies on some system-wide `.so` files: 26 | 27 | ```bash 28 | $ ldd walk-dynamic 29 | linux-vdso.so.1 => (0x00007fff899f4000) 30 | libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0e2a191000) 31 | /lib64/ld-linux-x86-64.so.2 (0x00007f0e2a55f000) 32 | ``` 33 | 34 | Refer to the `src` directory if you're courious about their C source code. 35 | 36 | 37 | ![bg](walk-cases.png) 38 | 39 | 40 | ## Case 1: Fully statically-linked ELF file 41 | 42 | The program `walk-static` is a fully statically-linked ELF executable. 43 | 44 | ★★ To build it into a minimal Docker image with `Dockerfile`: 45 | 46 | ``` 47 | $ docker build . 48 | ``` 49 | 50 | To see what's inside this image, starting from its root directory `/`: 51 | 52 | ``` 53 | $ docker run IMAGE-ID walk / 54 | ``` 55 | 56 | 57 | 58 | ## Case 2: Forget to link an ELF file with its dependent .so files 59 | 60 | The program `walk-dynamic` is a dynamically-linked ELF executable with runtime dependencies on some system-wide `.so` files. 61 | 62 | ★★ To build it into a minimal Docker image with `Dockerfile`: 63 | 64 | ``` 65 | $ docker build . 66 | ``` 67 | 68 | To see what's inside this image, starting from its root directory `/` (**will fail!**): 69 | 70 | ``` 71 | $ docker run IMAGE-ID walk / 72 | ``` 73 | 74 | 75 | ## Case 3: Link with dependent .so files extracted from Ubuntu 14.04 76 | 77 | Extract required `.so` files from Ubuntu 14.04: 78 | 79 | ``` 80 | 149120 Feb 25 2015 ld-linux-x86-64.so.2 81 | 1840928 Feb 25 2015 libc.so.6 82 | ``` 83 | 84 | Then, pack them (together with `walk-dynamic`) into the tarball `rootfs-from-ubuntu1404.tar.gz`. 85 | 86 | 87 | ★★ To build it into a minimal Docker image with `Dockerfile`: 88 | 89 | ``` 90 | $ docker build . 91 | ``` 92 | 93 | To see what's inside this image, starting from its root directory `/`: 94 | 95 | ``` 96 | $ docker run IMAGE-ID walk / 97 | ``` 98 | 99 | 100 | ## Case 4: Link with dependent .so files extracted from CentOS 5.11 101 | 102 | Extract required `.so` files from CentOS 5.11: 103 | 104 | ``` 105 | 142488 Sep 16 2014 ld-linux-x86-64.so.2 106 | 1720712 Sep 16 2014 libc.so.6 107 | ``` 108 | 109 | Then, pack them (together with `walk-dynamic`) into the tarball `rootfs-from-centos511.tar.gz`. 110 | 111 | 112 | ★★ To build it into a minimal Docker image with `Dockerfile`: 113 | 114 | ``` 115 | $ docker build . 116 | ``` 117 | 118 | To see what's inside this image, starting from its root directory `/`: 119 | 120 | ``` 121 | $ docker run IMAGE-ID walk / 122 | ``` 123 | 124 | 125 | 126 | ## Thinking: possible collision? 127 | 128 | System-wise `.so` files from Ubuntu 14.04: 129 | 130 | ``` 131 | 149120 Feb 25 2015 ld-linux-x86-64.so.2 132 | 1840928 Feb 25 2015 libc.so.6 133 | ``` 134 | 135 | System-wise `.so` files from CentOS 5.11: 136 | 137 | ``` 138 | 142488 Sep 16 2014 ld-linux-x86-64.so.2 139 | 1720712 Sep 16 2014 libc.so.6 140 | ``` 141 | 142 | Can these two suites co-exist at the same time? Dependency hell? 143 | -------------------------------------------------------------------------------- /build-walk/case1/Dockerfile: -------------------------------------------------------------------------------- 1 | # dockerize `walk-go` 2 | 3 | FROM scratch 4 | 5 | COPY walk-static /bin/walk 6 | -------------------------------------------------------------------------------- /build-walk/case1/walk-static: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/William-Yeh/docker-workshop/88c1d4b0674c3e1d2c2d6c3e2c02d406bcf6e791/build-walk/case1/walk-static -------------------------------------------------------------------------------- /build-walk/case2/Dockerfile: -------------------------------------------------------------------------------- 1 | # dockerize `walk-c` 2 | # 3 | # CAUTION: doesn't work due to the lack of required .so files. 4 | # 5 | 6 | FROM scratch 7 | 8 | COPY walk-dynamic /bin/walk 9 | -------------------------------------------------------------------------------- /build-walk/case2/walk-dynamic: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/William-Yeh/docker-workshop/88c1d4b0674c3e1d2c2d6c3e2c02d406bcf6e791/build-walk/case2/walk-dynamic -------------------------------------------------------------------------------- /build-walk/case3/Dockerfile: -------------------------------------------------------------------------------- 1 | # dockerize `walk-c`, with .so files extracted from Ubuntu 14.04 2 | 3 | FROM scratch 4 | 5 | Add rootfs-from-ubuntu1404.tar.gz . 6 | -------------------------------------------------------------------------------- /build-walk/case3/rootfs-from-ubuntu1404.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/William-Yeh/docker-workshop/88c1d4b0674c3e1d2c2d6c3e2c02d406bcf6e791/build-walk/case3/rootfs-from-ubuntu1404.tar.gz -------------------------------------------------------------------------------- /build-walk/case3/walk-dynamic: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/William-Yeh/docker-workshop/88c1d4b0674c3e1d2c2d6c3e2c02d406bcf6e791/build-walk/case3/walk-dynamic -------------------------------------------------------------------------------- /build-walk/case4/Dockerfile: -------------------------------------------------------------------------------- 1 | # dockerize `walk-c`, with .so files extracted from CentOS 5.11 2 | 3 | FROM scratch 4 | 5 | Add rootfs-from-centos511.tar.gz . 6 | -------------------------------------------------------------------------------- /build-walk/case4/rootfs-from-centos511.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/William-Yeh/docker-workshop/88c1d4b0674c3e1d2c2d6c3e2c02d406bcf6e791/build-walk/case4/rootfs-from-centos511.tar.gz -------------------------------------------------------------------------------- /build-walk/case4/walk-dynamic: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/William-Yeh/docker-workshop/88c1d4b0674c3e1d2c2d6c3e2c02d406bcf6e791/build-walk/case4/walk-dynamic -------------------------------------------------------------------------------- /build-walk/case5/Dockerfile: -------------------------------------------------------------------------------- 1 | # dockerize `walk-c`, with Ubuntu 14.04 as base image 2 | 3 | FROM ubuntu:14.04 4 | 5 | COPY walk-dynamic /bin/walk 6 | -------------------------------------------------------------------------------- /build-walk/case5/walk-dynamic: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/William-Yeh/docker-workshop/88c1d4b0674c3e1d2c2d6c3e2c02d406bcf6e791/build-walk/case5/walk-dynamic -------------------------------------------------------------------------------- /build-walk/src/README.md: -------------------------------------------------------------------------------- 1 | Build instructions of rootfs tarballs for walk executables 2 | === 3 | 4 | 5 | 6 | ## Source code of walk 7 | 8 | Two versions of the same functionality are provided: 9 | 10 | - `c-version`: written in C 11 | - `golang-version`: written in Go 12 | 13 | 14 | 15 | ## Generate rootfs tarballs for walk-* 16 | 17 | 18 | ### Prepare 19 | 20 | Use the `extract-elf-so` executable copied from the project: [`William-Yeh/extract-elf-so`](https://github.com/William-Yeh/extract-elf-so). 21 | 22 | Install: 23 | 24 | ```bash 25 | $ curl -sSL http://bit.ly/install-extract-elf-so \ 26 | | sudo bash 27 | ``` 28 | 29 | ### Extract required .so files from Ubuntu 14.04 30 | 31 | Execute the following command under Ubuntu 14.04: 32 | 33 | ```bash 34 | $ extract-elf-so \ 35 | -d /bin \ 36 | -n rootfs-from-ubuntu1404 \ 37 | -z \ 38 | walk-c 39 | ``` 40 | 41 | An `rootfs-from-ubuntu1404.tar.gz` tarball will be generated, if successful. 42 | 43 | 44 | ### Extract required .so files from CentOS 5.11 45 | 46 | Execute the following command under CentOS 5.11: 47 | 48 | ```bash 49 | $ extract-elf-so \ 50 | -d /bin \ 51 | -n rootfs-from-centos511 \ 52 | -z \ 53 | walk-c 54 | ``` 55 | 56 | An `rootfs-from-centos511.tar.gz` tarball will be generated, if successful. 57 | -------------------------------------------------------------------------------- /build-walk/src/c-version/Makefile: -------------------------------------------------------------------------------- 1 | all: walk.c 2 | gcc -std=c99 -o walk-dynamic walk.c 3 | gcc -std=c99 -o walk-static --static walk.c 4 | 5 | 6 | clean: 7 | rm -f walk-* 8 | -------------------------------------------------------------------------------- /build-walk/src/c-version/walk.c: -------------------------------------------------------------------------------- 1 | // Directory walker, excluding /dev /proc /sys. 2 | // 3 | // Usage: walk [starting path] 4 | // 5 | // @adapted from: http://linux.die.net/man/3/ftw 6 | // 7 | 8 | 9 | #define _XOPEN_SOURCE 500 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #define BUF_SIZE 512 18 | #define TIME_FORMAT "%F %R" 19 | #define DEFAULT_DIRECTORY "/" 20 | 21 | const char* EXCLUDE_PATH[] = { 22 | "/dev", 23 | "/proc", 24 | "/sys" 25 | }; 26 | 27 | 28 | int should_skip_this_path(const char* path) 29 | { 30 | int array_length = sizeof(EXCLUDE_PATH) / sizeof(EXCLUDE_PATH[0]); 31 | for (int i = 0; i < array_length; ++i) { 32 | if (strstr(path, EXCLUDE_PATH[i]) == path) { 33 | return 1; 34 | } 35 | } 36 | return 0; 37 | } 38 | 39 | static int 40 | display_info(const char* fpath, const struct stat* sb, 41 | int tflag, struct FTW* ftwbuf) 42 | { 43 | // last update time 44 | char utime[BUF_SIZE]; 45 | struct tm* timeinfo = localtime(&sb->st_mtime); 46 | strftime(utime, BUF_SIZE - 1, TIME_FORMAT, timeinfo); 47 | //printf("%s\n", utime); 48 | 49 | // file type 50 | const char* file_type = 51 | (tflag == FTW_D) ? "d" : (tflag == FTW_DNR) ? "dnr" : 52 | (tflag == FTW_DP) ? "dp" : (tflag == FTW_F) ? "f" : 53 | (tflag == FTW_NS) ? "ns" : (tflag == FTW_SL) ? "sl" : 54 | (tflag == FTW_SLN) ? "sln" : "???"; 55 | 56 | if (should_skip_this_path(fpath)) { 57 | return 0; 58 | } 59 | 60 | 61 | printf("%-3s %s %7jd %-40s\n", 62 | file_type, 63 | utime, 64 | (intmax_t) sb->st_size, 65 | fpath); 66 | return 0; /* To tell nftw() to continue */ 67 | } 68 | 69 | int 70 | main(int argc, char* argv[]) 71 | { 72 | int flags = 0; 73 | 74 | if (argc > 2 && strchr(argv[2], 'd') != NULL) 75 | flags |= FTW_DEPTH; 76 | if (argc > 2 && strchr(argv[2], 'p') != NULL) 77 | flags |= FTW_PHYS; 78 | 79 | if (nftw((argc < 2) ? DEFAULT_DIRECTORY : argv[1], display_info, 20, flags) 80 | == -1) { 81 | perror("nftw"); 82 | exit(EXIT_FAILURE); 83 | } 84 | exit(EXIT_SUCCESS); 85 | } 86 | -------------------------------------------------------------------------------- /build-walk/src/golang-version/Dockerfile-compile: -------------------------------------------------------------------------------- 1 | # building linux-amd64 native binary via Dockerized Go compiler 2 | # 3 | # @see https://registry.hub.docker.com/_/golang/ 4 | # 5 | 6 | # pull base image 7 | FROM golang:1.4.2 8 | MAINTAINER William Yeh 9 | 10 | ENV EXE_NAME walk_linux-amd64 11 | ENV GOPATH /opt 12 | WORKDIR /opt 13 | 14 | 15 | # fetch imported Go lib... 16 | RUN go get github.com/kr/fs text/tabwriter 17 | COPY walk.go /opt/ 18 | 19 | # compile... 20 | RUN go build -o $EXE_NAME 21 | 22 | 23 | 24 | # copy executable 25 | RUN mkdir -p /dist 26 | VOLUME [ "/dist" ] 27 | CMD cp *_linux-amd64 /dist 28 | -------------------------------------------------------------------------------- /build-walk/src/golang-version/Vagrantfile: -------------------------------------------------------------------------------- 1 | Vagrant.configure(2) do |config| 2 | config.vm.box = "williamyeh/ubuntu-trusty64-docker" 3 | 4 | config.vm.provision "shell", inline: <<-SHELL 5 | cd /vagrant 6 | ./build.sh 7 | SHELL 8 | end 9 | -------------------------------------------------------------------------------- /build-walk/src/golang-version/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # scirpt for compiling go source via Dockerized Go compiler. 4 | # 5 | # If you'd like to compile via native Go compiler: 6 | # 7 | # $ go install github.com/docopt/docopt-go 8 | # $ go build 9 | # 10 | 11 | set -e 12 | set -x 13 | 14 | 15 | IMAGE_NAME=app_build_temp 16 | docker build -t $IMAGE_NAME -f Dockerfile-compile . 17 | docker run --rm -v "$(pwd)/dist:/dist" $IMAGE_NAME 18 | 19 | docker rmi -f $IMAGE_NAME -------------------------------------------------------------------------------- /build-walk/src/golang-version/walk.go: -------------------------------------------------------------------------------- 1 | // Directory walker, excluding /dev /proc /sys. 2 | // 3 | // Usage: walk [starting path] 4 | // 5 | // adapted from: https://raw.githubusercontent.com/kr/fs/master/example_test.go 6 | // 7 | 8 | package main 9 | 10 | import ( 11 | "fmt" 12 | "os" 13 | "regexp" 14 | "strconv" 15 | 16 | "github.com/kr/fs" 17 | "text/tabwriter" 18 | ) 19 | 20 | var REGEX_EXCLUDE_PATH = regexp.MustCompile(`^/(dev|proc|sys)`) 21 | 22 | const DATE_LAYOUT string = "2006-01-02 15:04" 23 | 24 | var starting_path = "." 25 | 26 | func main() { 27 | 28 | if len(os.Args) > 1 { 29 | starting_path = os.Args[1] 30 | } 31 | 32 | w := new(tabwriter.Writer) 33 | w.Init(os.Stdout, 2, 0, 1, ' ', tabwriter.AlignRight) 34 | 35 | walker := fs.Walk(starting_path) 36 | for walker.Step() { 37 | if err := walker.Err(); err != nil { 38 | fmt.Fprintln(os.Stderr, err) 39 | continue 40 | } 41 | path := walker.Path() 42 | if REGEX_EXCLUDE_PATH.FindStringSubmatch(path) != nil { 43 | continue 44 | } 45 | 46 | info := walker.Stat() 47 | file_type := "f" 48 | if info.IsDir() { 49 | file_type = "d" 50 | } 51 | 52 | fmt.Fprintln(w, file_type+" \t"+(info.ModTime().Format(DATE_LAYOUT)+" \t"+strconv.FormatInt(info.Size(), 10)+"\t\t"+path)) 53 | } 54 | w.Flush() 55 | } 56 | -------------------------------------------------------------------------------- /build-walk/walk-cases.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/William-Yeh/docker-workshop/88c1d4b0674c3e1d2c2d6c3e2c02d406bcf6e791/build-walk/walk-cases.png -------------------------------------------------------------------------------- /build-walk/walk-dynamic: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/William-Yeh/docker-workshop/88c1d4b0674c3e1d2c2d6c3e2c02d406bcf6e791/build-walk/walk-dynamic -------------------------------------------------------------------------------- /build-walk/walk-static: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/William-Yeh/docker-workshop/88c1d4b0674c3e1d2c2d6c3e2c02d406bcf6e791/build-walk/walk-static -------------------------------------------------------------------------------- /config.md: -------------------------------------------------------------------------------- 1 | 行前準備 Part 2:預載範例程式碼 2 | === 3 | 4 | [ <-- Prev: [行前準備 Part 1](prepare.md) ] 5 | 6 | 7 | 為了節省課程現場下載程式及相關資源的時間及頻寬,請學員先在**網路暢通的地方**,根據指示備妥必要的軟體及設定。 8 | 9 | 整個過程可能會花上數十分鐘,請耐心等候。
10 | 整個過程可能會花上數十分鐘,請耐心等候。
11 | 整個過程可能會花上數十分鐘,請耐心等候。
12 | (因為很重要,所以要說三次。) 13 | 14 |   15 | 16 | ☛ 注意事項: 17 | 18 | - 程式範例會在每一梯次開課前一週才定案,因此,建議**等開課前一週再進行下列步驟**。 19 | 20 | - 進行以下步驟之前,請先確定 VirtualBox 之【預設機器資料夾】所在的磁碟上,仍有足夠空間,以容納各虛擬機內容及預載之 Docker 映像檔。建議至少要預留 15 GB: 21 | ![預留 VirtualBox 虛擬機所需空間](img/vbox-diskspace.png) 22 | 23 | - 進行以下步驟之前,建議您先關閉(甚至解除安裝)可能與 VirtualBox 相衝的其他虛擬機軟體。譬如說,以下命令可暫時關閉 Hyper-V(還需要你手動重新開機,才會生效): 24 | 25 | ``` 26 | bcdedit /set hypervisorlaunchtype off 27 | ``` 28 | 29 | 30 |   31 | 32 | 33 | ### 步驟一:Fork 本次 workshop 範例程式 34 | 35 | 1. 登入 GitHub 網站: https://github.com/ 36 | 37 | 2. 開啟 https://github.com/William-Yeh/docker-workshop 38 | 39 | 3. 按右上角的 ![Fork Button](img/icon-github-fork.png) 按鈕。 40 | 41 | 4. 幾秒鐘之內,你應該會被自動導引到自己帳號底下的 docker-workshop 專案。 42 | 43 | 44 | ### 步驟二:開啟終端機,以進行後續步驟 45 | 46 | Linux 及 Mac 使用者:請使用 xterm、終端機 (Terminal)、iTerm 或任何你慣用的終端機軟體。 47 | 48 | Windows 使用者: 49 | 50 | 1. 請先以「不含任何中文字」的使用者帳號,登入 Windows(否則會在某些 Vagrant 相關步驟出錯)。 51 | 2. 以『系統管理者』權限,打開【命令提示字元】軟體(否則**可能**會在某些 Vagrant 相關步驟出錯)。 52 | 53 | 54 | 55 | 56 | ### 步驟三:下載 workshop 範例程式 57 | 58 | 請先切換到你選定的工作目錄(Windows 用戶,請避免選用「含中文字」),譬如: 59 | 60 | ```shell 61 | cd YOUR_OWN_WORKING_DIRECTORY 62 | ``` 63 | 64 | 再下載範例: 65 | 66 | ```shell 67 | git clone https://github.com/你的帳號/docker-workshop.git 68 | ``` 69 | 70 | 71 | 72 | ### 步驟四:切換至此 workshop 目錄 73 | 74 | ```shell 75 | cd docker-workshop 76 | ``` 77 | 78 | 這個目錄,課堂上會反覆用到。建議你設桌面捷徑,以節省課堂現場切換目錄的時間。 79 | 80 | 81 | #### ⇡ 以上所列的幾個步驟,如有不清楚的,請見示範錄影: 82 | 83 | [![Docker Workshop - How to Fork Project](http://img.youtube.com/vi/n2ogtWHZRzo/0.jpg)](http://youtu.be/n2ogtWHZRzo) 84 | 85 | 86 | ### 步驟五:初始化 Vagrant 虛擬機 87 | 88 | 耗時最久的,就是這個步驟,請耐心等候。 89 | 90 | - 如果你的電腦是 Mac 或 Linux,請輸入: 91 | 92 | ```shell 93 | ./setup-vagrant 94 | ``` 95 | 96 | - 如果你的電腦是 Windows,請輸入: 97 | 98 | ```shell 99 | setup-vagrant 100 | ``` 101 | 102 | 103 | ### 步驟六:確認已設定完畢 104 | 105 | 輸入以下指令,查看各虛擬機的狀態: 106 | 107 | ```shell 108 | vagrant status 109 | ``` 110 | 111 | 如果看到以下畫面,三台虛擬機都呈現 "poweroff" 狀態,就表示已經順利設定完畢: 112 | 113 | ``` 114 | Current machine states: 115 | 116 | main poweroff (virtualbox) 117 | centos poweroff (virtualbox) 118 | registry poweroff (virtualbox) 119 | 120 | This environment represents multiple VMs. The VMs are all listed 121 | above with their current state. For more information about a specific 122 | VM, run `vagrant status NAME`. 123 | ``` 124 | -------------------------------------------------------------------------------- /img/download-virtualbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/William-Yeh/docker-workshop/88c1d4b0674c3e1d2c2d6c3e2c02d406bcf6e791/img/download-virtualbox.png -------------------------------------------------------------------------------- /img/icon-github-fork.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/William-Yeh/docker-workshop/88c1d4b0674c3e1d2c2d6c3e2c02d406bcf6e791/img/icon-github-fork.png -------------------------------------------------------------------------------- /img/icon-github-watch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/William-Yeh/docker-workshop/88c1d4b0674c3e1d2c2d6c3e2c02d406bcf6e791/img/icon-github-watch.png -------------------------------------------------------------------------------- /img/vbox-diskspace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/William-Yeh/docker-workshop/88c1d4b0674c3e1d2c2d6c3e2c02d406bcf6e791/img/vbox-diskspace.png -------------------------------------------------------------------------------- /img/vbox-win64-error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/William-Yeh/docker-workshop/88c1d4b0674c3e1d2c2d6c3e2c02d406bcf6e791/img/vbox-win64-error.png -------------------------------------------------------------------------------- /intro.md: -------------------------------------------------------------------------------- 1 | Docker 建置實戰講堂 2 | === 3 | 4 | #### 副標 5 | 與名師 Step by Step 6 | 實機操作學習 Docker 建置與應用 7 | 8 | 報名系統: 9 | 10 | - [第五梯次](http://containersummit.ithome.com.tw/workshop/#ticket) : 2015-06-27 (高雄) 11 | - 第四梯次 : 2015-05-09 (台北) 12 | - 第三梯次 : 2015-04-11 (台北) 13 | - 第二梯次 : 2015-03-07 (台北) 14 | - 第一梯次 : 2015-02-07 (台北) 15 | 16 | 17 | ## 課程目標 18 | 19 | 從實作中正確掌握 Docker 基礎知識及最佳實務,擁有進一步評估、鑽研進階議題的能力。 20 | 21 | 22 | ## 課程簡介 23 | 24 | - Docker 技術總覽 25 | - 實習環境介紹 26 | - 常用的工具指令:docker cli、docker compose 27 | - 常用的 Dockerfile 指令 28 | - 從極簡化 Docker image 領會 Docker 三大特色 29 | - Docker 化典型伺服器軟體(以 Redis、Nginx 為例) 30 | - 從程式源碼建置 Docker 化軟體(以 PHP、Node.js 為例) 31 | - GitHub 與 Docker Hub 連動 32 | - Docker 網路模型 33 | - Docker 化軟體要素(暨常見地雷):port、volume、daemon off 34 | - 綜合運用 35 | 36 | 37 | ## 課程特色 38 | 39 | 1. **Docker 的 Why**:從 DevOps 角度,分析 Docker 的優異特性:dependency、isolation、lightweight、standard。 40 | 41 | 2. **Docker 的 How**:從雲端時代軟體架構角度(尤其是 [12-factor app](http://12factor.net/)),搭配重點案例,探討 Dockerfile 及「Docker 化軟體」設計要點。 42 | 43 | 3. **Docker 的 What**:涵蓋〈[一張圖總結 Docker 的命令](http://philipzheng.gitbooks.io/docker_practice/content/appendix_command/README.html#-docker-)〉重點流程及指令。 44 | 45 | 4. **做中學,不空談**:所有觀念,都搭配現場實作及 Docker Hub 案例研討,給你帶得走的能力。 46 | 47 | 48 | ## 課程時數 49 | 50 | 6 小時,涵蓋 90% 教材內容。 51 | 52 | 53 | ## 適合對象 54 | 55 | 本課程以「觀念講述」及「實機操作」兩部分交織進行。觀念講述部分,適合對 Docker 感興趣的 IT 從業人員,尤以後端系統為主。實機操作部分,適合不排斥在 Linux 命令列輸入指令的人。 56 | 57 | 58 | ## 報名須知 59 | 60 | 1. 本課程含大量實機操作內容,請自備 **64 位元**的筆記型電腦(Windows、Mac、Linux 皆可,但需要是 **64 位元**的版本)。 61 | 62 | 2. 建議上課前學習 Git 版本控制指令: 63 | 64 | - 課程的範例原始碼、與 Docker Hub 的連動,都需要和 GitHub 打交道,所以,至少要會基本的 git 命令(init、clone、add、commit、push...)。 65 | - 如欲補充基礎,請參考 Will 保哥(黃保翕)的〈[30 天精通 Git 版本控管](https://github.com/doggy8088/Learn-Git-in-30-days)〉系列文章。萬一時間有限,至少要將第 01~07、24~25、30 天的內容消化完畢。 66 | 67 | 3. 具備以下能力能讓你學得更快: 68 | 69 | - 用過任何一種程式語言或框架(譬如:Bash、C、Go、Java、Node.js、PHP、Python、Ruby...),撰寫可在 Linux 上執行的程式,並部署之。 70 | 71 | - 曾在 Linux 上安裝過任何一種開放源碼伺服器軟體(譬如:Apache HTTP Server、MongoDB、MySQL、Nginx、WordPress...)。 72 | 73 | - 在任何一種雲端平台(Amazon EC2、DigitalOcean、Google Compute Engine、Linode、Microsoft Azure...),完成上述任務。 74 | -------------------------------------------------------------------------------- /linking-full/README.md: -------------------------------------------------------------------------------- 1 | # Container Linking 2 | 3 | 4 | This directory is to demonstrate the "[container linking](https://docs.docker.com/userguide/dockerlinks/)" feature of Docker, using [wrk](https://github.com/William-Yeh/docker-wrk) (written in C and Lua), [Spray](https://github.com/William-Yeh/Docker-Spray-HttpServer) (written in Scala), [Fluentd](https://github.com/William-Yeh/docker-fluentd) (written in Ruby), and [Elasticsearch + Kibana](http://www.elasticsearch.org/overview/kibana/) (written in Java) as example. 5 | 6 | ![Overview of the demo](./flows.png "Overview of the demo") 7 | 8 | 9 | 10 | ## Preparation 11 | 12 | Prepare environments for experiment. 13 | 14 | **CAUTION: This may take minutes. Do it at a place with good bandwidth.** 15 | 16 | ``` 17 | $ docker pull williamyeh/wrk 18 | $ docker pull williamyeh/spray-httpserver 19 | $ docker pull williamyeh/fluentd 20 | $ docker pull digitalwonderland/elasticsearch 21 | ``` 22 | 23 | 24 | ## Usage 25 | 26 | 1. Clear all unused container records: 27 | 28 | ``` 29 | $ docker rm `docker ps --no-trunc -a -q` 30 | ``` 31 | 32 | 33 | 2. Start the http server (with the container name `spray`): 34 | 35 | ``` 36 | $ docker run -d --name spray \ 37 | williamyeh/spray-httpserver 38 | ``` 39 | 40 | 3. Tail the logs of the http server, and keep this console open: 41 | 42 | ``` 43 | $ docker logs -f spray 44 | ``` 45 | 46 | 4. Open another console. Use `wrk` to benchmark the http server: 47 | 48 | ``` 49 | $ docker run --link spray:httpserver \ 50 | williamyeh/wrk http://httpserver:8080/ 51 | ``` 52 | 53 | 54 | 5. Use `wrk` to benchmark the http server, with random IPs as input: 55 | 56 | ``` 57 | $ docker run --link spray:httpserver \ 58 | -v `pwd`:/data \ 59 | williamyeh/wrk -s wrk-script.lua http://httpserver:8080/ 60 | ``` 61 | 62 | 63 | 6. Generate Fluentd conf file `td-agent.conf` for capturing logs produced by the `spray` container: 64 | 65 | ``` 66 | $ ./gen-fluentd-conf.sh spray > td-agent.conf 67 | ``` 68 | 69 | 70 | 7. Use `fluentd` to collect the `spray` logs: 71 | 72 | ``` 73 | $ docker run -it \ 74 | -v /var/lib/docker/containers:/var/lib/docker/containers:ro \ 75 | -v `pwd`:/etc/td-agent:ro \ 76 | -v `pwd`:/data \ 77 | --net=host \ 78 | williamyeh/fluentd start 79 | ``` 80 | 81 | 82 | 8. Re-run previous `wrk` task to see the `fluentd` output! 83 | 84 | 85 | 9. Start the `Elasticsearch` server: 86 | 87 | ``` 88 | $ docker run -d --name elasticsearch \ 89 | -p 9200:9200 \ 90 | digitalwonderland/elasticsearch 91 | ``` 92 | 93 | 94 | 10. Use browser to open the Kibana page: 95 | http://localhost:9200/_plugin/kibana3/ 96 | 97 | 98 | 11. You may also re-run previous `wrk` task to see the Kibana dashboard! 99 | -------------------------------------------------------------------------------- /linking-full/fig.yml: -------------------------------------------------------------------------------- 1 | --- 2 | spray: 3 | image: williamyeh/spray-httpserver 4 | 5 | wrk: 6 | image: williamyeh/wrk 7 | command: http://httpserver:8080/ 8 | links: 9 | - spray:httpserver 10 | -------------------------------------------------------------------------------- /linking-full/flows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/William-Yeh/docker-workshop/88c1d4b0674c3e1d2c2d6c3e2c02d406bcf6e791/linking-full/flows.png -------------------------------------------------------------------------------- /linking-full/gen-fluentd-conf.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # generates fluentd conf on-the-fly for specific running container. 4 | # 5 | # NOTE: see docker-gen for more complete solution: 6 | # http://jasonwilder.com/blog/2014/03/17/docker-log-management-using-fluentd/ 7 | # 8 | 9 | if [ $# -lt 1 ]; then 10 | echo "Generates fluentd conf on-the-fly for specific running container." 11 | echo "Usage: gen-fluentd-conf.sh container_name [pos_file_directory]" 12 | exit 1 13 | fi 14 | 15 | 16 | readonly CONTAINER_NAME=$1 17 | readonly CONTAINER_ID=`sudo docker inspect --format="{{ .Id }}" $CONTAINER_NAME` 18 | readonly LOG_FULLPATH=/var/lib/docker/containers/$CONTAINER_ID/$CONTAINER_ID-json.log 19 | 20 | readonly POS_FILE_DIRECTORY=${2:-/data} 21 | readonly POS_FILE_FULLPATH=$POS_FILE_DIRECTORY/$CONTAINER_ID-json.log.pos 22 | 23 | #echo $CONTAINER_ID 24 | #echo $LOG_FULLPATH 25 | 26 | 27 | 28 | 29 | 30 | cat < 32 | type tail 33 | format json 34 | time_key time 35 | time_format %Y-%m-%dT%H:%M:%S.%L 36 | 37 | path $LOG_FULLPATH 38 | pos_file $POS_FILE_FULLPATH 39 | rotate_wait 5 40 | 41 | tag docker.$CONTAINER_NAME.$CONTAINER_ID 42 | 43 | 44 | 45 | 46 | type copy 47 | 48 | 49 | # for debug (see /var/log/td-agent.log) 50 | type stdout 51 | 52 | 53 | 54 | # @see https://github.com/uken/fluent-plugin-elasticsearch 55 | type elasticsearch 56 | 57 | #host localhost 58 | #port 9200 59 | logstash_format true 60 | logstash_prefix docker.spray 61 | include_tag_key true 62 | tag_key _key 63 | 64 | 65 | EOF 66 | -------------------------------------------------------------------------------- /linking-full/wrk-script.lua: -------------------------------------------------------------------------------- 1 | -- 2 | -- wrk script for generating random IPs. 3 | -- adapted from: https://github.com/fiorix/freegeoip/blob/master/wrk-test.lua 4 | -- 5 | 6 | 7 | -- https://github.com/wg/wrk 8 | -- wrk -c 1000 -d 10s -s wrk-test.lua http://localhost:8080 9 | 10 | math.randomseed(os.time()) 11 | randomIP = function() 12 | return 13 | math.random(1,254) .. "." .. 14 | math.random(1,254) .. "." .. 15 | math.random(1,254) .. "." .. 16 | math.random(1,254) 17 | end 18 | 19 | request = function() 20 | path = "/echo/" .. randomIP() 21 | return wrk.format(nil, path) 22 | end 23 | 24 | 25 | 26 | original_license_statement = [[ 27 | 28 | Copyright (c) 2013 Alexandre Fiori. All rights reserved. 29 | 30 | Redistribution and use in source and binary forms, with or without 31 | modification, are permitted provided that the following conditions are 32 | met: 33 | 34 | * Redistributions of source code must retain the above copyright 35 | notice, this list of conditions and the following disclaimer. 36 | * Redistributions in binary form must reproduce the above 37 | copyright notice, this list of conditions and the following disclaimer 38 | in the documentation and/or other materials provided with the 39 | distribution. 40 | * The names of authors or contributors may NOT be used to endorse or 41 | promote products derived from this software without specific prior 42 | written permission. 43 | 44 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 45 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 46 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 47 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 48 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 49 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 50 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 51 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 52 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 53 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 54 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 55 | 56 | ]] 57 | -------------------------------------------------------------------------------- /make-registry-box/IMAGE-LIST: -------------------------------------------------------------------------------- 1 | #--------------------------------------# 2 | # basic base image 3 | # 4 | 5 | debian:wheezy 6 | debian:jessie 7 | ubuntu:precise 8 | ubuntu:trusty 9 | ubuntu:14.04 10 | ubuntu:latest 11 | centos:5.11 12 | busybox:latest 13 | 14 | # Docker Hub: https://registry.hub.docker.com/_/php/ 15 | php:5.6.6-cli 16 | #php:5.6.6-fpm 17 | 18 | # Docker Hub: https://registry.hub.docker.com/_/node/ 19 | node:0.10.36-slim 20 | node:0.10.36-onbuild 21 | 22 | #--------------------------------------# 23 | # app 24 | # 25 | 26 | redis:2.8.19 27 | nginx:1.9.0 28 | haproxy:1.5.12 29 | mysql:5.6.22 30 | wordpress:4.1.0 31 | 32 | # Docker Hub: https://registry.hub.docker.com/_/mongo/ 33 | # Dockerfile: https://github.com/docker-library/mongo/blob/1d641659a75cf2f8ce1b517c7fc2a0ebfd033eed/2.6/Dockerfile 34 | #mongo:2.6.7 35 | 36 | svendowideit/ambassador 37 | jwilder/nginx-proxy 38 | 39 | williamyeh/redis:2.8.19 40 | williamyeh/wrk 41 | #williamyeh/spray-httpserver 42 | #williamyeh/fluentd 43 | #digitalwonderland/elasticsearch 44 | #elasticsearch:1.4.4 45 | 46 | #ipython/notebook 47 | #ghost:0.5.9 48 | -------------------------------------------------------------------------------- /make-registry-box/README.md: -------------------------------------------------------------------------------- 1 | Building a Docker Registry box with pre-loaded images 2 | === 3 | 4 | 5 | ## Name 6 | 7 | Official box name in Atlas (was: Vagrant Cloud): [`williamyeh/docker-workshop-registry`](https://atlas.hashicorp.com/williamyeh/boxes/docker-workshop-registry). 8 | 9 | 10 | 11 | ## Purpose 12 | 13 | To build a Vagrant box, which: 14 | 15 | - derives from [`williamyeh/insecure-registry`](https://vagrantcloud.com/williamyeh/insecure-registry) box (refer to [this](https://github.com/William-Yeh/docker-enabled-vagrant/tree/master/insecure-registry) for implementation details). 16 | - pre-loads Docker images listed in the `IMAGE-LIST` file from Docker Hub. 17 | 18 | 19 | 20 | ## Build it on your own... 21 | 22 | ### Prerequisite 23 | 24 | Install [`vagrant-hosts`](https://github.com/adrienthebo/vagrant-hosts) plugin: 25 | 26 | ```bash 27 | vagrant plugin install vagrant-hosts 28 | ``` 29 | 30 | ### Build! 31 | 32 | 33 | ```bash 34 | $ ./build.sh 35 | ``` 36 | 37 | If everything is OK, you'll obtain a box file `docker-workshop-registry.box`. Feel free to place it on your local disk or cloud storage (Dropbox, S3, etc). 38 | -------------------------------------------------------------------------------- /make-registry-box/Vagrantfile: -------------------------------------------------------------------------------- 1 | Vagrant.require_version ">= 1.7.2" 2 | 3 | 4 | $script = < 7 | 1.1:安裝步驟
8 | 1.2:Windows 作業系統注意事項
9 | 1.3:磁碟空間 10 | 2. 註冊 GitHub 帳號 11 | 3. 註冊 Docker Hub 帳號 12 | 4. 列印參考資料 13 | 14 | 15 | [ Next: --> [行前準備 Part 2](config.md) ] 16 | 17 | 18 | 19 | ## 1. 安裝軟體 20 | 21 | 本課程的「實機操作」部分,需要學員自備 **64 位元**的筆記型電腦。而這些筆電的作業系統,可能是 Windows,也可能是 Mac OS X,或各種 Linux distributions。 22 | 23 | 為了讓課程有個一致的實作環境,減少干擾施教者與學習者的環境變因,我們統一使用 [Vagrant](http://www.vagrantup.com/) + [VirtualBox](https://www.virtualbox.org/) 虛擬機器組合,作為課堂實作的統一環境。對這種軟體組合的技術細節感興趣的,請見本文附錄:【關於 Vagrant】。這裡先只講軟體安裝步驟。 24 | 25 | 26 | ### 1.1:安裝步驟 27 | 28 | 為了順利進行本系列文章的操作,請先依照以下步驟安裝 Vagrant 及 VirtualBox: 29 | 30 | 1. 去 Vagrant 官網的[下載頁](http://www.vagrantup.com/downloads.html),下載適合的安裝檔,執行之。 31 | 32 | 2. 去 VirtualBox 官網的[下載頁](https://www.virtualbox.org/wiki/Downloads),下載兩個安裝檔: 33 | 34 | - VirtualBox platform packages 35 | - VirtualBox Extension Pack 36 | 37 | 並依序執行之。 38 | 39 | ![下載必要的 VirtualBox 安裝檔案](img/download-virtualbox.png) 40 | 41 | 42 | ### 1.2:Windows 作業系統注意事項 43 | 44 | 在 Windows 上,下載 VirtualBox 兩個安裝檔時,最好先置於「完全由**英文字**或**阿拉伯數字**所組成的路徑」上,再執行安裝程序,比較不會出現奇奇怪怪的亂碼問題。 45 | 46 | - 安裝 VirtualBox 時,如果遇到以下錯誤: 47 | 48 | ![找不到指定的檔案](img/vbox-win64-error.png) 49 | 50 | 請先切換到放置下載檔案的目錄,找出剛剛下載回來的安裝檔名(以我的例子:`VirtualBox-4.3.22-98236-Win.exe`),再依序執行以下命令: 51 | 52 | ```bat 53 | VirtualBox-4.3.22-98236-Win -extract 54 | cd VirtualBox 55 | dir 56 | ``` 57 | 58 | 你應該會看到一個 `msi` 類型的安裝檔,請執行它。 59 | 60 | - 安裝 VirtualBox Extension Pack 時,如果遇到 “The installer failed with exit code: 1” 錯誤,請先切換到放置下載檔案的目錄,找出剛剛下載回來的安裝檔名(以我的例子:`Oracle_VM_VirtualBox_Extension_Pack-4.3.22-98236.vbox-extpack`),再依序執行以下命令: 61 | 62 | ```bat 63 | VBoxManage extpack uninstall "Oracle VM VirtualBox Extension Pack" 64 | VBoxManage extpack cleanup 65 | VBoxManage extpack install --replace Oracle_VM_VirtualBox_Extension_Pack-4.3.22-98236.vbox-extpack 66 | ``` 67 | 68 | 69 | 70 | 最後,為了 Vagrant 運作順暢,你還需要一個「**純命令列**的 ssh 程式」(像 [PuTTY](http://www.chiark.greenend.org.uk/~sgtatham/putty/)、[PieTTY](http://ntu.csie.org/~piaip/pietty/) 或[可攜版](http://jedi.org/PieTTYPortable/)之類的 GUI 程式,可能會在某些進階步驟踩到地雷;非 power user 請勿嘗試)。本課程建議您安裝以下這個「**純命令列**的 ssh 程式」: 71 | 72 | - [Git for the Windows platform](http://git-scm.com/download/win),不但有 `git.exe`,裡面也含有一枚 `ssh.exe`。 73 | 74 | 安裝後,記得要去【控制台】把 `ssh.exe` 所在路徑加到 `PATH` 環境變數。 75 | 76 | 77 | ### 1.3:磁碟空間 78 | 79 | 請確定 VirtualBox 之【預設機器資料夾】所在的磁碟上,仍有足夠空間,以容納各虛擬機內容及預載之 Docker 映像檔。 80 | 81 | 建議至少要預留 15 GB: 82 | ![預留 VirtualBox 虛擬機所需空間](img/vbox-diskspace.png) 83 | 84 | 85 | 86 | 87 | ## 2. 註冊 GitHub 帳號 88 | 89 | 本課程會帶你實機操作,將欲「Docker 化」的程式碼置於 [GitHub](https://github.com/) 上,以供後續 Docker Hub 串接運用。 90 | 91 | 如果你還沒有 GitHub 帳號,請到[這裡](https://github.com/)註冊,並在本機端設定好 SSH key。 92 | 93 | GitHub 註冊及設定完畢後,請再進行以下步驟,以訂閱 Docker Workshop 範例程式的異動通知: 94 | 95 | A. 開啟 https://github.com/William-Yeh/docker-workshop 96 | 97 | B. 按右上角的 ![Watch Button](img/icon-github-watch.png) 按鈕。 98 | 99 | 之後,範例程式的任何異動,會自動送到你的 GitHub 登入畫面及 email。這個管道也會通知你,最近梯次的範例程式碼,何時正式定案。 100 | 101 | 102 | ## 3. 註冊 Docker Hub 帳號 103 | 104 | 本課程會帶你實機操作,如何利用 Docker 官方的 [Docker Hub](https://registry.hub.docker.com/) 服務,串接置於 GitHub 的程式碼,自動建置 Docker image。 105 | 106 | 如果你還沒有 Docker Hub 帳號,請到[這裡](https://hub.docker.com/account/signup/)註冊。 107 | 108 | 109 | 110 | ## 4. 列印參考資料 111 | 112 | 有幾份資料,在課堂上會反覆用到。因著作權所限,我們無法主動提供紙本。如果您習慣在紙本上註記,請於參加課程之前自行列印,攜至課堂上。 113 | 114 | - [一張圖總結 Docker 的命令](http://philipzheng.gitbooks.io/docker_practice/content/_images/cmd_logic.png) ← 彩色 115 | 116 | - [Docker 命令查詢](http://philipzheng.gitbooks.io/docker_practice/content/appendix_command/README.html) 117 | 118 | - [Dockerfile 指令](http://philipzheng.gitbooks.io/docker_practice/content/dockerfile/instructions.html) 119 | 120 | 121 | 122 | 123 | ## 附錄:關於 Vagrant 124 | 125 | 許多 Docker 入門教程會建議 Windows 或 Mac 用戶安裝 [boot2docker](http://boot2docker.io/)。但基於以下理由,本課程不採用這種方案: 126 | 127 | - boot2docker 會在你的電腦上安裝一台 [Tiny Core Linux](http://tinycorelinux.net/) 虛擬機,優點是輕薄短小,但缺點是,與實務常見的 Linux 生態嚴重脫節(實務上,哪些 server 會用 Tiny Core Linux?)。DevOps 觀念告訴我們,Dev 和 Ops 的環境愈接近,愈有利及早發現問題。 128 | 129 | - boot2docker 無法輕易做出獨立、可重複再現的組態,遑論多台主機的 cluster 實驗環境。 130 | 131 | 相較之下,Vagrant 方案則有下列好處: 132 | 133 | - 可直接在本機端模擬出伺服主機所採用的作業系統及組態,符合 DevOps 的最佳實務。 134 | 135 | - 可輕易做出獨立、可重複再現的多台主機 cluster 實驗環境,更可儲存組態快照 (snapshot),不怕玩壞系統,可快速還原回原始設定。 136 | 137 | - 反正都要學一點新的東西,與其學習 boot2docker 獨有指令,不如學習用途更廣的 Vagrant。 138 | 139 | 如果你還不熟悉 Vagrant + VirtualBox 軟體組合,請先閱讀講師在 [CodeData](http://www.codedata.com.tw/) 連載的〈[Vagrant Tutorial](http://www.codedata.com.tw/social-coding/vagrant-tutorial-1-developer-and-vm)〉系列文章,尤其是第二篇:〈[跟著流浪漢把玩虛擬機](http://www.codedata.com.tw/social-coding/vagrant-tutorial-2-playing-vm-with-vagrant)〉,**至少這篇要照著做過一遍!**才能確定你已經成功安裝好 Virtualbox + Vagrant (+ ssh),才能進行實機操作課程。 140 | 141 | 課堂上,也會帶領大家操作一些常用的 Vagrant 指令。 142 | -------------------------------------------------------------------------------- /provision/setup-docker-tools.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # download and install handy Docker tools 4 | # 5 | 6 | readonly BASE_URL="https://raw.githubusercontent.com/William-Yeh/docker-host-tools/master/" 7 | readonly APP=( "DOCKER" "docker-rm-stopped" "docker-rmi-repo" "docker-inspect-attr" ) 8 | 9 | 10 | cd /usr/local/bin 11 | 12 | for i in "${APP[@]}"; do 13 | NAME=$i 14 | curl -o $NAME "$BASE_URL$NAME" 15 | chmod a+x $NAME 16 | done 17 | 18 | 19 | readonly OTHER_TOOLS=( "http://stedolan.github.io/jq/download/linux64/jq" ) 20 | for i in "${OTHER_TOOLS[@]}"; do 21 | curl -L -O $i 22 | done 23 | chmod a+x * 24 | -------------------------------------------------------------------------------- /provision/setup-env.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # append PRIVATE_DOCKER_REGISTRY global env 4 | # 5 | 6 | cat <> /etc/environment 7 | PRIVATE_DOCKER_REGISTRY="registry.com" 8 | EOF 9 | 10 | -------------------------------------------------------------------------------- /provision/setup-hosts.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # append host entry into /etc/hosts 4 | # 5 | # [NOTE] better way -- use 'vagrant-hosts' plugin: 6 | # https://github.com/adrienthebo/vagrant-hosts 7 | # 8 | 9 | cat <> /etc/hosts 10 | 10.0.0.200 registry.com 11 | EOF 12 | -------------------------------------------------------------------------------- /reverse-proxy/README.md: -------------------------------------------------------------------------------- 1 | Reverse proxy + Docker example 2 | === 3 | 4 | ## Purpose 5 | 6 | Demonstrate how to use reverse proxy for backend application servers, all in the Docker's world. 7 | 8 | 9 | ## Software stack 10 | 11 | ![bg](reverse-proxy.png) 12 | 13 | 14 | #### Nginx 15 | 16 | - [Reverse proxy](http://nginx.com/resources/admin-guide/reverse-proxy/) 17 | 18 | - [Load balancing](http://nginx.com/resources/admin-guide/load-balancer/) 19 | 20 | - [SSL termination](http://nginx.com/resources/admin-guide/nginx-ssl-termination/): use `make-cert.sh` to generate self-signed certificate. 21 | 22 | 23 | #### HAProxy 24 | 25 | - Reverse proxy 26 | 27 | - Load balancing 28 | 29 | - Active health monitoring 30 | 31 | - SSL termination: use `make-cert.sh` to generate self-signed certificate. 32 | 33 | 34 | 35 | #### Node.js application server instances 36 | 37 | - Source code in `app` directory. 38 | - *N* instances. 39 | - High availability and zero-downtime deployments via Nginx or HAProxy. 40 | 41 | 42 | #### Redis server 43 | 44 | - Shared datastore across all Node.js application instances. 45 | - [Persistence](http://redis.io/topics/persistence): RDB and AOF modes. 46 | 47 | 48 | ## Usage #1: simple case 49 | 50 | First, start the whole software stack: 51 | 52 | ```bash 53 | $ docker-compose up -d 54 | 55 | $ docker ps 56 | ``` 57 | 58 | 59 | Second, connect to Nginx via HTTP and HTTPS : 60 | 61 | ```bash 62 | $ curl -v http://localhost:10080 63 | 64 | $ curl -v --insecure https://localhost:10443 65 | 66 | ``` 67 | 68 | Third, connect to HAProxy via HTTP and HTTPS : 69 | 70 | ```bash 71 | $ curl -v http://localhost:10090 72 | 73 | $ curl -v --insecure https://localhost:10091 74 | ``` 75 | 76 | 77 | ## Usage #2: zero-downtime deployments 78 | 79 | **NOTE**: Nginx supports "[`health_check`](http://nginx.com/resources/admin-guide/load-balancer/#health_active)" only in its commercial product "Nginx Plus" (see [this](http://nginx.org/en/docs/http/ngx_http_upstream_module.html#health_check) and [this](http://nginx.com/products/application-health-checks/)). Therefore, only HAProxy is demonstrated in this zero-downtime case. 80 | 81 | First, start the whole software stack: 82 | 83 | ```bash 84 | $ docker-compose -f docker-compose-2.yml up -d 85 | 86 | $ docker ps 87 | ``` 88 | 89 | Second, use browser to open HAProxy statistics report: `http://localhost:10100/` 90 | 91 | 92 | Third, connect to HAProxy via HTTP and HTTPS : 93 | 94 | ```bash 95 | $ curl -v http://localhost/ 96 | 97 | $ curl -v --insecure https://localhost/ 98 | ``` 99 | 100 | 101 | Fourth, stop one of the application instances (e.g., `app1`): 102 | 103 | ```bash 104 | $ docker-compose stop app1 105 | ``` 106 | 107 | Then, try to connect via HTTP and HTTPS. Any downtime? 108 | 109 | 110 | Fifth, let the stopped instance come back to live: 111 | 112 | ```bash 113 | $ docker-compose start app1 114 | ``` 115 | 116 | Then, try to connect via HTTP and HTTPS. Does the instance recieve packets from HAProxy again? 117 | -------------------------------------------------------------------------------- /reverse-proxy/app/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:0.10.36-onbuild 2 | 3 | EXPOSE 3000 4 | -------------------------------------------------------------------------------- /reverse-proxy/app/index.js: -------------------------------------------------------------------------------- 1 | // A simple web server that generates dyanmic content based on responses from Redis 2 | // 3 | // Adapted from: https://github.com/mranney/node_redis/blob/master/examples/web_server.js 4 | // 5 | 6 | var http = require('http'), 7 | ip = require("ip"); 8 | 9 | var PORT = process.env.PORT || 3000 ; 10 | var REDIS_HOST = process.env.REDIS_HOST || '127.0.0.1' ; 11 | var REDIS_PORT = process.env.REDIS_PORT || 6379 ; 12 | 13 | 14 | function get_remote_ip(req) { 15 | var ip_address = null; 16 | try { 17 | ip_address = req.headers['x-forwarded-for']; 18 | } 19 | catch (err) { 20 | ip_address = req.connection.remoteAddress; 21 | } 22 | return ip_address; 23 | } 24 | 25 | 26 | function report_health(resp) { 27 | resp.writeHead(200, { 28 | "Content-Type": "text/plain" 29 | }); 30 | resp.write("OK"); 31 | resp.end(); 32 | } 33 | 34 | 35 | var redis_client = require('redis').createClient(REDIS_PORT, REDIS_HOST); 36 | var server = http.createServer(function(request, response) { 37 | 38 | console.log(request.url); 39 | 40 | // skip uninteresting URL requests 41 | if (request.url === '/favicon.ico') { 42 | return; 43 | } 44 | else if (request.url === '/health') { 45 | report_health(response); 46 | return; 47 | } 48 | 49 | 50 | response.writeHead(200, { 51 | "Content-Type": "text/plain" 52 | }); 53 | 54 | var total_requests; 55 | 56 | redis_client.incr("requests", function(err, reply) { 57 | total_requests = reply; // stash response in outer scope 58 | }); 59 | 60 | redis_client.hincrby("ip", get_remote_ip(request), 1); 61 | redis_client.hgetall("ip", function(err, reply) { 62 | // This is the last reply, so all of the previous replies must have completed already 63 | response.write( 64 | "Total requests: " + total_requests + "\n\n" + 65 | "My IP: " + ip.address() + "\n\n" + 66 | "Remote IP count: \n"); 67 | Object.keys(reply).forEach(function(ip) { 68 | response.write(" " + ip + ": " + reply[ip] + "\n"); 69 | }); 70 | response.end(); 71 | }); 72 | 73 | }).listen(PORT); 74 | 75 | console.log('Server listening on port', PORT); 76 | -------------------------------------------------------------------------------- /reverse-proxy/app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "http-server-example", 3 | "version": "0.0.1", 4 | "description": "A simple http server with counter stored in Redis", 5 | "scripts": { 6 | "start": "node index.js" 7 | }, 8 | "dependencies": { 9 | "redis": "*", 10 | "ip": "*" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /reverse-proxy/certificate.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIID/TCCAuWgAwIBAgIJALapUPkV3mB6MA0GCSqGSIb3DQEBCwUAMIGUMQswCQYD 3 | VQQGEwJUVzEPMA0GA1UECAwGVGFpcGVpMQ8wDQYDVQQHDAZUYWlwZWkxFDASBgNV 4 | BAoMC1dpbGxpYW0gWWVoMQswCQYDVQQLDAJSRDEYMBYGA1UEAwwPd2lsbGlhbS15 5 | ZWgubmV0MSYwJAYJKoZIhvcNAQkBFhd3aWxsaWFtLnBqeWVoQGdtYWlsLmNvbTAe 6 | Fw0xNTA1MjExNTE1NTNaFw0xNjA1MjAxNTE1NTNaMIGUMQswCQYDVQQGEwJUVzEP 7 | MA0GA1UECAwGVGFpcGVpMQ8wDQYDVQQHDAZUYWlwZWkxFDASBgNVBAoMC1dpbGxp 8 | YW0gWWVoMQswCQYDVQQLDAJSRDEYMBYGA1UEAwwPd2lsbGlhbS15ZWgubmV0MSYw 9 | JAYJKoZIhvcNAQkBFhd3aWxsaWFtLnBqeWVoQGdtYWlsLmNvbTCCASIwDQYJKoZI 10 | hvcNAQEBBQADggEPADCCAQoCggEBANN2QBcBQwQO+KJAHj+4dLQeAxw2fC9sFVyr 11 | p6QLRUKnmIyTZmyTTpAQCTVev1TlnAmHllfM/TgYytxHKr+5gQf8fvxxqDXZGnYW 12 | 5vmt/pHfHLEoKYv/3AZ2ND23Da6tnTw52BjkQa67rIbBja0vitWNLiy/2I409OAd 13 | Ym2WjFvMntUaXwUnyPaRfBxaCvXk0G0dD2B55sxmaXchxhVwfzmC2l3DPVEbQF/s 14 | 9wNQ+msSFGy4qo6W2DQ+5vhqHZeBxbWM7FBJ6H/3T/nckNwh6INOKP3VzroDWQ8x 15 | lnAL2casBaxtGkgm3zvzzkwb2lQ2K2TRIH1/452deuocO17BqFECAwEAAaNQME4w 16 | HQYDVR0OBBYEFOwIll8hcydreGPcM0LtNx6ePw2uMB8GA1UdIwQYMBaAFOwIll8h 17 | cydreGPcM0LtNx6ePw2uMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB 18 | AIfiL5tpq7Tw8O6R6aM/4vJKe5HwQKeuf/xNuF8SBVX48ZOs62F2BVdnQA9WVpbW 19 | 4VfWJ4h04pOGqMLZz4Xpk2tJ9boCrCfl2MFL35wjJ0LM+NGwp+W8qHwqXlHIZY9j 20 | abierovSIQrzDGqy7qPF23t+Xh1uAzOO8Q1nPyG0xp6AV9jyEGWDmsd5uH1/iCDy 21 | uLXrPhaO4brEBE1wtmOqSdoBugCKBfdxVBjLF/n9rXRRu7vqynRQzojn6BVUDj6Z 22 | 1QPQYyjsiYKVJ6qARB0hmXEmz60bcShgYeYRmZqxjT/iHXFJGfZljzd16wCeytpj 23 | vDdY2+oB+CiBEDQLsZmDGNI= 24 | -----END CERTIFICATE----- 25 | -------------------------------------------------------------------------------- /reverse-proxy/certificate.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDTdkAXAUMEDvii 3 | QB4/uHS0HgMcNnwvbBVcq6ekC0VCp5iMk2Zsk06QEAk1Xr9U5ZwJh5ZXzP04GMrc 4 | Ryq/uYEH/H78cag12Rp2Fub5rf6R3xyxKCmL/9wGdjQ9tw2urZ08OdgY5EGuu6yG 5 | wY2tL4rVjS4sv9iONPTgHWJtloxbzJ7VGl8FJ8j2kXwcWgr15NBtHQ9geebMZml3 6 | IcYVcH85gtpdwz1RG0Bf7PcDUPprEhRsuKqOltg0Pub4ah2XgcW1jOxQSeh/90/5 7 | 3JDcIeiDTij91c66A1kPMZZwC9nGrAWsbRpIJt87885MG9pUNitk0SB9f+OdnXrq 8 | HDtewahRAgMBAAECggEBAJ6OJ/gX5hwA7cUatpOoxzjW2BYrdGpKbKoTu5txJ/mW 9 | mPeu/jmjKmEy5PSzmlsZ3yn2FHC5L5UEYfdRFWi0u181oDHBNxNJOmIZQg8su5i8 10 | 5lKffqeOrXfa4cj0nLnBTAiAhtwDKozOA8r3DjgxUbRWK606HDJk2sfAwLDTFWMu 11 | aTITr2yH/S1HwSyYa0a1dRTddLkz9vl3kNc1y1UfDlThzSh+aKDFx1PwgDapjCID 12 | zZG8oAeLZWEf5LVRaEqH/5zqNMRNWF7Lotun9tB8K8ffO87k0QxEtBO2KGPNNffp 13 | BMuCoF3wwZwAM+NfJG0gLJVjRgWh1eXXAeVprcd3eZECgYEA8XMul3+QCpLtx40y 14 | 1gnsJvrc+sNyPOtHr19CJKOwB27OFVXszdU2ZJukYHZjRQ+821k56B9+ts8I5Pqm 15 | Ivlr46dFxj+Cjp951pM+6hVwGhRCGJ3JhYylSCMVUY7l/k+jiob4VHGrQ40Pglbx 16 | wv2xRhDWlPjqmPw15dRYw3YtwDsCgYEA4DRybe+0feiVcGUXyXZrAN9I2GBi9K6N 17 | g0YUVq6Gajnw4LvXmLo64QJSBu+8M959gXtM/PfcHGmJ6h/99sNCfKa46u8Sbaw0 18 | 3VMjVoEUJDmvYFeK69YWRqQ/dvGqFrPoTYc7p8PY8h3zfQ4iRx57QnJh+Bopfy/J 19 | 8OrxW9qhXOMCgYA0j+mVq3x1ANVourFVbSWOus/+eyvUXTfm0qr4hPXeOF3+wQzj 20 | JkZIEqXvJfaoYyuu6La1dJ3GOD3sczBVrsyw64pCBTNrzwXcE4P/u5kC5GQbLcZg 21 | H2Uf1hte/OfOvBGTJ5zJ7VDmTMASlNDerRG5ehLsrV+M3GLzXI3SR1jgXwKBgEQ4 22 | 8VDujbd6XG609EYDWJANYXcl7TaTHtCBNJMjzBbqxpc70WDR2jS5pggiTtxhqUML 23 | J+QZ78pdeu/ZCEhcJhEUElS6pprkublXIPujj2NugiUIvmcA4Api1ET3SFBcMiXV 24 | LpvgBlW2M28sK9YEOnF/qLv8CgB/pC1A8GyI3G0NAoGANuP+vY9Fp5SWORS2wmJL 25 | hPTS62tpLHs/6leDDSlplpzTg5dURHGTb0TSj4VCoRLrHcm4oQZauh3hbtI9VarH 26 | gnm+92Llj15ZPvGCw3nwea2U79aNQz5+nlWIJKOkzUnRD5boyCguhIxvYT3V4SQ4 27 | 7DKnvYs0kjVXB4UkBNpHplY= 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /reverse-proxy/certificate.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIID/TCCAuWgAwIBAgIJALapUPkV3mB6MA0GCSqGSIb3DQEBCwUAMIGUMQswCQYD 3 | VQQGEwJUVzEPMA0GA1UECAwGVGFpcGVpMQ8wDQYDVQQHDAZUYWlwZWkxFDASBgNV 4 | BAoMC1dpbGxpYW0gWWVoMQswCQYDVQQLDAJSRDEYMBYGA1UEAwwPd2lsbGlhbS15 5 | ZWgubmV0MSYwJAYJKoZIhvcNAQkBFhd3aWxsaWFtLnBqeWVoQGdtYWlsLmNvbTAe 6 | Fw0xNTA1MjExNTE1NTNaFw0xNjA1MjAxNTE1NTNaMIGUMQswCQYDVQQGEwJUVzEP 7 | MA0GA1UECAwGVGFpcGVpMQ8wDQYDVQQHDAZUYWlwZWkxFDASBgNVBAoMC1dpbGxp 8 | YW0gWWVoMQswCQYDVQQLDAJSRDEYMBYGA1UEAwwPd2lsbGlhbS15ZWgubmV0MSYw 9 | JAYJKoZIhvcNAQkBFhd3aWxsaWFtLnBqeWVoQGdtYWlsLmNvbTCCASIwDQYJKoZI 10 | hvcNAQEBBQADggEPADCCAQoCggEBANN2QBcBQwQO+KJAHj+4dLQeAxw2fC9sFVyr 11 | p6QLRUKnmIyTZmyTTpAQCTVev1TlnAmHllfM/TgYytxHKr+5gQf8fvxxqDXZGnYW 12 | 5vmt/pHfHLEoKYv/3AZ2ND23Da6tnTw52BjkQa67rIbBja0vitWNLiy/2I409OAd 13 | Ym2WjFvMntUaXwUnyPaRfBxaCvXk0G0dD2B55sxmaXchxhVwfzmC2l3DPVEbQF/s 14 | 9wNQ+msSFGy4qo6W2DQ+5vhqHZeBxbWM7FBJ6H/3T/nckNwh6INOKP3VzroDWQ8x 15 | lnAL2casBaxtGkgm3zvzzkwb2lQ2K2TRIH1/452deuocO17BqFECAwEAAaNQME4w 16 | HQYDVR0OBBYEFOwIll8hcydreGPcM0LtNx6ePw2uMB8GA1UdIwQYMBaAFOwIll8h 17 | cydreGPcM0LtNx6ePw2uMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB 18 | AIfiL5tpq7Tw8O6R6aM/4vJKe5HwQKeuf/xNuF8SBVX48ZOs62F2BVdnQA9WVpbW 19 | 4VfWJ4h04pOGqMLZz4Xpk2tJ9boCrCfl2MFL35wjJ0LM+NGwp+W8qHwqXlHIZY9j 20 | abierovSIQrzDGqy7qPF23t+Xh1uAzOO8Q1nPyG0xp6AV9jyEGWDmsd5uH1/iCDy 21 | uLXrPhaO4brEBE1wtmOqSdoBugCKBfdxVBjLF/n9rXRRu7vqynRQzojn6BVUDj6Z 22 | 1QPQYyjsiYKVJ6qARB0hmXEmz60bcShgYeYRmZqxjT/iHXFJGfZljzd16wCeytpj 23 | vDdY2+oB+CiBEDQLsZmDGNI= 24 | -----END CERTIFICATE----- 25 | -----BEGIN PRIVATE KEY----- 26 | MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDTdkAXAUMEDvii 27 | QB4/uHS0HgMcNnwvbBVcq6ekC0VCp5iMk2Zsk06QEAk1Xr9U5ZwJh5ZXzP04GMrc 28 | Ryq/uYEH/H78cag12Rp2Fub5rf6R3xyxKCmL/9wGdjQ9tw2urZ08OdgY5EGuu6yG 29 | wY2tL4rVjS4sv9iONPTgHWJtloxbzJ7VGl8FJ8j2kXwcWgr15NBtHQ9geebMZml3 30 | IcYVcH85gtpdwz1RG0Bf7PcDUPprEhRsuKqOltg0Pub4ah2XgcW1jOxQSeh/90/5 31 | 3JDcIeiDTij91c66A1kPMZZwC9nGrAWsbRpIJt87885MG9pUNitk0SB9f+OdnXrq 32 | HDtewahRAgMBAAECggEBAJ6OJ/gX5hwA7cUatpOoxzjW2BYrdGpKbKoTu5txJ/mW 33 | mPeu/jmjKmEy5PSzmlsZ3yn2FHC5L5UEYfdRFWi0u181oDHBNxNJOmIZQg8su5i8 34 | 5lKffqeOrXfa4cj0nLnBTAiAhtwDKozOA8r3DjgxUbRWK606HDJk2sfAwLDTFWMu 35 | aTITr2yH/S1HwSyYa0a1dRTddLkz9vl3kNc1y1UfDlThzSh+aKDFx1PwgDapjCID 36 | zZG8oAeLZWEf5LVRaEqH/5zqNMRNWF7Lotun9tB8K8ffO87k0QxEtBO2KGPNNffp 37 | BMuCoF3wwZwAM+NfJG0gLJVjRgWh1eXXAeVprcd3eZECgYEA8XMul3+QCpLtx40y 38 | 1gnsJvrc+sNyPOtHr19CJKOwB27OFVXszdU2ZJukYHZjRQ+821k56B9+ts8I5Pqm 39 | Ivlr46dFxj+Cjp951pM+6hVwGhRCGJ3JhYylSCMVUY7l/k+jiob4VHGrQ40Pglbx 40 | wv2xRhDWlPjqmPw15dRYw3YtwDsCgYEA4DRybe+0feiVcGUXyXZrAN9I2GBi9K6N 41 | g0YUVq6Gajnw4LvXmLo64QJSBu+8M959gXtM/PfcHGmJ6h/99sNCfKa46u8Sbaw0 42 | 3VMjVoEUJDmvYFeK69YWRqQ/dvGqFrPoTYc7p8PY8h3zfQ4iRx57QnJh+Bopfy/J 43 | 8OrxW9qhXOMCgYA0j+mVq3x1ANVourFVbSWOus/+eyvUXTfm0qr4hPXeOF3+wQzj 44 | JkZIEqXvJfaoYyuu6La1dJ3GOD3sczBVrsyw64pCBTNrzwXcE4P/u5kC5GQbLcZg 45 | H2Uf1hte/OfOvBGTJ5zJ7VDmTMASlNDerRG5ehLsrV+M3GLzXI3SR1jgXwKBgEQ4 46 | 8VDujbd6XG609EYDWJANYXcl7TaTHtCBNJMjzBbqxpc70WDR2jS5pggiTtxhqUML 47 | J+QZ78pdeu/ZCEhcJhEUElS6pprkublXIPujj2NugiUIvmcA4Api1ET3SFBcMiXV 48 | LpvgBlW2M28sK9YEOnF/qLv8CgB/pC1A8GyI3G0NAoGANuP+vY9Fp5SWORS2wmJL 49 | hPTS62tpLHs/6leDDSlplpzTg5dURHGTb0TSj4VCoRLrHcm4oQZauh3hbtI9VarH 50 | gnm+92Llj15ZPvGCw3nwea2U79aNQz5+nlWIJKOkzUnRD5boyCguhIxvYT3V4SQ4 51 | 7DKnvYs0kjVXB4UkBNpHplY= 52 | -----END PRIVATE KEY----- 53 | -------------------------------------------------------------------------------- /reverse-proxy/docker-compose-2.yml: -------------------------------------------------------------------------------- 1 | # 2 | # Zero-downtime deployment. 3 | # 4 | # Feel free to stop/start individual appN instances, 5 | # and see how HAProxy reacts. 6 | # 7 | 8 | haproxy: 9 | image: haproxy:1.5.12 10 | restart: always 11 | volumes: 12 | - ./haproxy-2.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro 13 | - ./certificate.pem:/usr/local/etc/haproxy/certificate.pem:ro 14 | net: "host" 15 | 16 | 17 | app1: 18 | build: app 19 | ports: 20 | - "3001:3000" 21 | links: 22 | - redisserver 23 | environment: 24 | - REDIS_HOST=redisserver 25 | 26 | app2: 27 | build: app 28 | ports: 29 | - "3002:3000" 30 | links: 31 | - redisserver 32 | environment: 33 | - REDIS_HOST=redisserver 34 | 35 | 36 | redisserver: 37 | image: williamyeh/redis:2.8.19 38 | restart: always 39 | volumes: 40 | - .:/data 41 | - ./redis.conf:/etc/redis/redis.conf:ro 42 | command: 43 | - start 44 | -------------------------------------------------------------------------------- /reverse-proxy/docker-compose.yml: -------------------------------------------------------------------------------- 1 | nginx: 2 | image: nginx:1.9.0 3 | restart: always 4 | volumes: 5 | - .:/etc/nginx:ro 6 | ports: 7 | - "10080:80" 8 | - "10443:443" 9 | links: 10 | - app1:node1 11 | - app2:node2 12 | 13 | 14 | haproxy: 15 | image: haproxy:1.5.12 16 | restart: always 17 | volumes: 18 | - .:/usr/local/etc/haproxy:ro 19 | ports: 20 | - "10090:80" 21 | - "10091:443" 22 | - "10100:1936" 23 | links: 24 | - app1:node1 25 | - app2:node2 26 | 27 | 28 | app1: 29 | build: app 30 | links: 31 | - redisserver 32 | environment: 33 | - REDIS_HOST=redisserver 34 | 35 | 36 | app2: 37 | build: app 38 | links: 39 | - redisserver 40 | environment: 41 | - REDIS_HOST=redisserver 42 | 43 | 44 | redisserver: 45 | image: williamyeh/redis:2.8.19 46 | restart: always 47 | volumes: 48 | - .:/data 49 | - ./redis.conf:/etc/redis/redis.conf:ro 50 | command: 51 | - start 52 | -------------------------------------------------------------------------------- /reverse-proxy/haproxy-2.cfg: -------------------------------------------------------------------------------- 1 | global 2 | maxconn 4096 3 | nbproc 2 4 | #debug 5 | #daemon # should be disabled in Docker 6 | log 127.0.0.1 local0 7 | tune.ssl.default-dh-param 2048 8 | 9 | 10 | defaults 11 | mode http 12 | option httplog 13 | log global 14 | retries 3 15 | option redispatch 16 | timeout client 30s 17 | timeout connect 30s 18 | timeout server 30s 19 | 20 | 21 | frontend access_http 22 | bind *:80 23 | mode http 24 | reqadd X-Forwarded-Proto:\ http 25 | default_backend node-app 26 | 27 | 28 | frontend access_https 29 | bind *:443 ssl no-sslv3 crt /usr/local/etc/haproxy/certificate.pem 30 | mode http 31 | option httpclose 32 | option forwardfor 33 | reqadd X-Forwarded-Proto:\ https 34 | default_backend node-app 35 | 36 | 37 | backend node-app 38 | mode http 39 | balance roundrobin 40 | option forwardfor 41 | http-request set-header X-Forwarded-Port %[dst_port] 42 | http-request add-header X-Forwarded-Proto https if { ssl_fc } 43 | option httpchk HEAD /health HTTP/1.1\r\nHost:localhost 44 | server server1 127.0.0.1:3001 check 45 | server server2 127.0.0.1:3002 check 46 | #server server1 node1:3000 cookie server1 weight 1 maxconn 1024 check 47 | #server server2 node2:3000 cookie server2 weight 1 maxconn 1024 check 48 | 49 | 50 | listen stats *:10100 51 | #listen stats *:1936 52 | stats enable 53 | stats uri / 54 | #stats hide-version 55 | stats refresh 5s 56 | -------------------------------------------------------------------------------- /reverse-proxy/haproxy.cfg: -------------------------------------------------------------------------------- 1 | global 2 | maxconn 4096 3 | nbproc 2 4 | #debug 5 | #daemon # should be disabled in Docker 6 | log 127.0.0.1 local0 7 | tune.ssl.default-dh-param 2048 8 | 9 | 10 | defaults 11 | mode http 12 | option httplog 13 | log global 14 | retries 3 15 | option redispatch 16 | timeout connect 5000 17 | timeout client 50000 18 | timeout server 50000 19 | 20 | 21 | frontend access_http 22 | bind *:80 23 | mode http 24 | reqadd X-Forwarded-Proto:\ http 25 | default_backend node-app 26 | 27 | 28 | frontend access_https 29 | bind *:443 ssl no-sslv3 crt /usr/local/etc/haproxy/certificate.pem 30 | mode http 31 | option httpclose 32 | option forwardfor 33 | reqadd X-Forwarded-Proto:\ https 34 | default_backend node-app 35 | 36 | 37 | backend node-app 38 | mode http 39 | balance roundrobin 40 | option forwardfor 41 | http-request set-header X-Forwarded-Port %[dst_port] 42 | http-request add-header X-Forwarded-Proto https if { ssl_fc } 43 | option httpchk HEAD /health HTTP/1.1\r\nHost:localhost 44 | server server1 node1:3000 check 45 | server server2 node2:3000 check 46 | #server server1 node1:3000 cookie server1 weight 1 maxconn 1024 check 47 | #server server2 node2:3000 cookie server2 weight 1 maxconn 1024 check 48 | 49 | 50 | listen stats *:1936 51 | stats enable 52 | stats uri / 53 | #stats hide-version 54 | stats refresh 5s 55 | -------------------------------------------------------------------------------- /reverse-proxy/make-cert.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | openssl req -new -x509 -sha256 -newkey rsa:2048 -days 365 -nodes -out ./certificate.crt -keyout ./certificate.key 4 | 5 | cat certificate.crt certificate.key > certificate.pem 6 | -------------------------------------------------------------------------------- /reverse-proxy/nginx.conf: -------------------------------------------------------------------------------- 1 | worker_processes auto; 2 | 3 | events { worker_connections 1024; } 4 | 5 | http { 6 | 7 | upstream node-app { 8 | least_conn; 9 | zone backend 64k; 10 | server node1:3000 weight=10 max_fails=3 fail_timeout=30s; 11 | server node2:3000 weight=10 max_fails=3 fail_timeout=30s; 12 | } 13 | 14 | server_tokens off; 15 | 16 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 17 | ssl_ciphers HIGH:!aNULL:!MD5; 18 | ssl_session_cache shared:SSL:10m; 19 | ssl_session_timeout 10m; 20 | 21 | server { 22 | listen 80; 23 | listen 443 ssl; 24 | 25 | ssl_certificate /etc/nginx/certificate.crt; 26 | ssl_certificate_key /etc/nginx/certificate.key; 27 | 28 | location / { 29 | proxy_pass http://node-app; 30 | #health_check; 31 | 32 | proxy_http_version 1.1; 33 | proxy_set_header HOST $host; 34 | proxy_set_header X-Forwarded-Proto $scheme; 35 | proxy_set_header X-Real-IP $remote_addr; 36 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 37 | 38 | proxy_set_header Upgrade $http_upgrade; 39 | proxy_set_header Connection 'upgrade'; 40 | proxy_cache_bypass $http_upgrade; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /reverse-proxy/pull-images.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | DOCKER pull nginx:1.9.0 4 | DOCKER pull haproxy:1.5.12 5 | DOCKER pull node:0.10.36-onbuild 6 | DOCKER pull williamyeh/redis:2.8.19 7 | -------------------------------------------------------------------------------- /reverse-proxy/redis.conf: -------------------------------------------------------------------------------- 1 | 2 | # Working directory for "dump.rdb" and "appendonly.aof" 3 | dir /data/ 4 | 5 | 6 | save 10 5 7 | 8 | 9 | appendonly yes 10 | appendfsync everysec 11 | -------------------------------------------------------------------------------- /reverse-proxy/reverse-proxy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/William-Yeh/docker-workshop/88c1d4b0674c3e1d2c2d6c3e2c02d406bcf6e791/reverse-proxy/reverse-proxy.png -------------------------------------------------------------------------------- /setup-vagrant: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | readonly HOSTS=( "main" "centos" "registry" ) 4 | 5 | for i in "${HOSTS[@]}"; do 6 | NAME=$i 7 | vagrant up --provision $NAME 8 | vagrant halt 9 | done 10 | -------------------------------------------------------------------------------- /setup-vagrant.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | set HOSTS=( main centos registry ) 4 | 5 | for %%i in %HOSTS% do ( 6 | vagrant up --provision %%i 7 | vagrant halt %%i 8 | ) 9 | -------------------------------------------------------------------------------- /vagrant-tutorial/Vagrantfile: -------------------------------------------------------------------------------- 1 | Vagrant.configure(2) do |config| 2 | 3 | config.vm.box = "williamyeh/ubuntu-trusty64-docker" 4 | 5 | #config.vm.box = "ubuntu/trusty64" 6 | #config.vm.box = "ubuntu/precise64" 7 | #config.vm.box = "bento/centos-7.1" 8 | #config.vm.box = "bento/centos-6.7" 9 | #config.vm.box = "debian/jessie64" 10 | #config.vm.box = "yungsang/coreos" 11 | #config.vm.box = "yungsang/coreos-alpha" 12 | #config.vm.box = "yungsang/coreos-beta" 13 | 14 | end 15 | --------------------------------------------------------------------------------