├── .gitignore ├── LICENSE ├── README.md ├── Vagrantfile ├── lesson-01 ├── README.md ├── images │ ├── docker-and-linux-kernel.png │ ├── docker-arch.png │ ├── docker-daemon-cli.png │ ├── docker-filesystem.png │ ├── docker-in-osx.png │ ├── docker-libcontainer-lxc.png │ ├── docker-machine-logo.png │ ├── docker-network.png │ ├── docker-solution.png │ ├── docker-swarm-logo.png │ ├── docker-toolbox-logo.png │ └── docker-vs-vm.png └── keynote.md ├── lesson-02 ├── README.md └── keynote.md ├── lesson-03 ├── README.md ├── images │ ├── dm-block-mapping.png │ ├── dm-remap.png │ └── dm-snapshot.png └── keynote.md ├── lesson-04 ├── app │ ├── Dockerfile │ └── app.rb ├── dockerfiles │ ├── Dockerfile │ └── Dockerfile-entrypoint-shell ├── files │ ├── file1.txt │ └── file2.txt ├── keynote.md └── ruby │ └── Dockerfile ├── lesson-05 ├── README.md ├── auth │ ├── domain.crt │ ├── domain.key │ ├── htpasswd │ ├── registry.conf │ └── registry.password ├── certs │ ├── domain.crt │ └── domain.key ├── docker-compose.yml ├── images │ └── index-and-registry.png └── keynote.md ├── lesson-06 └── keynote.md ├── lesson-07 ├── images │ └── etcd-ambassador-flow.png └── keynote.md ├── lesson-08 └── keynote.md ├── lesson-09 ├── example-1 │ ├── Dockerfile │ ├── app.py │ ├── docker-compose.yml │ └── requirements.txt ├── example-2 │ └── docker-compose.yml └── keynote.md ├── lesson-10 ├── images │ └── docker-machine.png └── keynote.md ├── lesson-11 └── keynote.md ├── lesson-12 ├── images │ ├── cnm-model.jpg │ ├── docker-turtles-communication.jpg │ ├── docker_bridged.png │ ├── docker_container.png │ ├── etcd-ambassador-flow.png │ ├── flannel-packet.png │ ├── flannel.png │ ├── socketplane.png │ └── weave-arch.png └── keynote.md ├── lesson-13 ├── README.md ├── docker-compose.yml └── keynote.md ├── lesson-14 ├── Dockerfile ├── README.md ├── images │ └── jenkins_logo.png └── keynote.md └── lesson-15 ├── README.md ├── images ├── coreos.png ├── deis.png ├── etcd.png ├── flannel.png ├── fleet.png ├── flocker.png ├── hyper.png ├── k8s.png ├── lxd.png ├── mesos.png ├── rkt.png └── runc.png └── keynote.md /.gitignore: -------------------------------------------------------------------------------- 1 | lesson-05/data 2 | */memo.txt 3 | */README.md 4 | .vagrant/ 5 | */scripts/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | CC0 1.0 Universal 2 | 3 | Statement of Purpose 4 | 5 | The laws of most jurisdictions throughout the world automatically confer 6 | exclusive Copyright and Related Rights (defined below) upon the creator and 7 | subsequent owner(s) (each and all, an "owner") of an original work of 8 | authorship and/or a database (each, a "Work"). 9 | 10 | Certain owners wish to permanently relinquish those rights to a Work for the 11 | purpose of contributing to a commons of creative, cultural and scientific 12 | works ("Commons") that the public can reliably and without fear of later 13 | claims of infringement build upon, modify, incorporate in other works, reuse 14 | and redistribute as freely as possible in any form whatsoever and for any 15 | purposes, including without limitation commercial purposes. These owners may 16 | contribute to the Commons to promote the ideal of a free culture and the 17 | further production of creative, cultural and scientific works, or to gain 18 | reputation or greater distribution for their Work in part through the use and 19 | efforts of others. 20 | 21 | For these and/or other purposes and motivations, and without any expectation 22 | of additional consideration or compensation, the person associating CC0 with a 23 | Work (the "Affirmer"), to the extent that he or she is an owner of Copyright 24 | and Related Rights in the Work, voluntarily elects to apply CC0 to the Work 25 | and publicly distribute the Work under its terms, with knowledge of his or her 26 | Copyright and Related Rights in the Work and the meaning and intended legal 27 | effect of CC0 on those rights. 28 | 29 | 1. Copyright and Related Rights. A Work made available under CC0 may be 30 | protected by copyright and related or neighboring rights ("Copyright and 31 | Related Rights"). Copyright and Related Rights include, but are not limited 32 | to, the following: 33 | 34 | i. the right to reproduce, adapt, distribute, perform, display, communicate, 35 | and translate a Work; 36 | 37 | ii. moral rights retained by the original author(s) and/or performer(s); 38 | 39 | iii. publicity and privacy rights pertaining to a person's image or likeness 40 | depicted in a Work; 41 | 42 | iv. rights protecting against unfair competition in regards to a Work, 43 | subject to the limitations in paragraph 4(a), below; 44 | 45 | v. rights protecting the extraction, dissemination, use and reuse of data in 46 | a Work; 47 | 48 | vi. database rights (such as those arising under Directive 96/9/EC of the 49 | European Parliament and of the Council of 11 March 1996 on the legal 50 | protection of databases, and under any national implementation thereof, 51 | including any amended or successor version of such directive); and 52 | 53 | vii. other similar, equivalent or corresponding rights throughout the world 54 | based on applicable law or treaty, and any national implementations thereof. 55 | 56 | 2. Waiver. To the greatest extent permitted by, but not in contravention of, 57 | applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and 58 | unconditionally waives, abandons, and surrenders all of Affirmer's Copyright 59 | and Related Rights and associated claims and causes of action, whether now 60 | known or unknown (including existing as well as future claims and causes of 61 | action), in the Work (i) in all territories worldwide, (ii) for the maximum 62 | duration provided by applicable law or treaty (including future time 63 | extensions), (iii) in any current or future medium and for any number of 64 | copies, and (iv) for any purpose whatsoever, including without limitation 65 | commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes 66 | the Waiver for the benefit of each member of the public at large and to the 67 | detriment of Affirmer's heirs and successors, fully intending that such Waiver 68 | shall not be subject to revocation, rescission, cancellation, termination, or 69 | any other legal or equitable action to disrupt the quiet enjoyment of the Work 70 | by the public as contemplated by Affirmer's express Statement of Purpose. 71 | 72 | 3. Public License Fallback. Should any part of the Waiver for any reason be 73 | judged legally invalid or ineffective under applicable law, then the Waiver 74 | shall be preserved to the maximum extent permitted taking into account 75 | Affirmer's express Statement of Purpose. In addition, to the extent the Waiver 76 | is so judged Affirmer hereby grants to each affected person a royalty-free, 77 | non transferable, non sublicensable, non exclusive, irrevocable and 78 | unconditional license to exercise Affirmer's Copyright and Related Rights in 79 | the Work (i) in all territories worldwide, (ii) for the maximum duration 80 | provided by applicable law or treaty (including future time extensions), (iii) 81 | in any current or future medium and for any number of copies, and (iv) for any 82 | purpose whatsoever, including without limitation commercial, advertising or 83 | promotional purposes (the "License"). The License shall be deemed effective as 84 | of the date CC0 was applied by Affirmer to the Work. Should any part of the 85 | License for any reason be judged legally invalid or ineffective under 86 | applicable law, such partial invalidity or ineffectiveness shall not 87 | invalidate the remainder of the License, and in such case Affirmer hereby 88 | affirms that he or she will not (i) exercise any of his or her remaining 89 | Copyright and Related Rights in the Work or (ii) assert any associated claims 90 | and causes of action with respect to the Work, in either case contrary to 91 | Affirmer's express Statement of Purpose. 92 | 93 | 4. Limitations and Disclaimers. 94 | 95 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 96 | surrendered, licensed or otherwise affected by this document. 97 | 98 | b. Affirmer offers the Work as-is and makes no representations or warranties 99 | of any kind concerning the Work, express, implied, statutory or otherwise, 100 | including without limitation warranties of title, merchantability, fitness 101 | for a particular purpose, non infringement, or the absence of latent or 102 | other defects, accuracy, or the present or absence of errors, whether or not 103 | discoverable, all to the greatest extent permissible under applicable law. 104 | 105 | c. Affirmer disclaims responsibility for clearing rights of other persons 106 | that may apply to the Work or any use thereof, including without limitation 107 | any person's Copyright and Related Rights in the Work. Further, Affirmer 108 | disclaims responsibility for obtaining any necessary consents, permissions 109 | or other rights required for any use of the Work. 110 | 111 | d. Affirmer understands and acknowledges that Creative Commons is not a 112 | party to this document and has no duty or obligation with respect to this 113 | CC0 or use of the Work. 114 | 115 | For more information, please see 116 | 117 | 118 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # docker101 2 | “Docker入门与实践”课程讲义及参考 3 | 4 | # 目录结构 5 | 6 | 每个文件夹内容如下 7 | 8 | - keynote.md:课程讲义 9 | - README.md:一些额外的备注、参考,以及实验脚本、步骤。 10 | - 实验源文件等其他文件 11 | 12 | # 注意事项 13 | 14 | - 请不要拷贝keynote.md里的命令,可能会有格式问题(Markdown的list格式) 15 | - 请拷贝README.md中的命令 16 | 17 | 18 | # 有问题? 19 | 20 | [请提issue](https://github.com/liubin/docker101/issues) 21 | 22 | # 全部视频连接 23 | 24 | * [Docker基本概念](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2720) 25 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker1.jpg) 26 | * [Docker实现原理](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2721) 27 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker2.jpg) 28 | * [Docker组件介绍](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2722) 29 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker3.jpg) 30 | * [Docker实操环境介绍](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2723) 31 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker4.jpg) 32 | * [什么是Docker容器](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2724) 33 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker5.jpg) 34 | * [深入Docker容器](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2725) 35 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker6.jpg) 36 | * [Docker容器的生命周期管理](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2726) 37 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker7.jpg) 38 | * [认识Docker镜像](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2727) 39 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker8.jpg) 40 | * [手工构建Docker镜像](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2728) 41 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker9.jpg) 42 | * [使用Dockerfile构建Ruby镜像](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2729) 43 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker10.jpg) 44 | * [Dockerfile指令说明](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2730) 45 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker11.jpg) 46 | * [构建私有镜像服务器](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2731) 47 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker12.jpg) 48 | * [为私有镜像服务添加Basic认证...](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2732) 49 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker13.jpg) 50 | * [为私有镜像服务添加Token认证...](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2733) 51 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker14.jpg) 52 | * [Docker Hub和自动构建](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2734) 53 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker15.jpg) 54 | * [Docker容器连接](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2735) 55 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker16.jpg) 56 | * [创建和使用数据卷](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2736) 57 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker17.jpg) 58 | * [使用数据卷容器](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2737) 59 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker18.jpg) 60 | * [使用Docker Compose](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2738) 61 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker19.jpg) 62 | * [Docker Compose配置文件解说](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2739) 63 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker20.jpg) 64 | * [初识Docker Machine](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2740) 65 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker21.jpg) 66 | * [使用Docker Machine创建云主机...](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2741) 67 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker22.jpg) 68 | * [Docker Machine命令详解](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2742) 69 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker23.jpg) 70 | * [Swarm简介](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2743) 71 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker24.jpg) 72 | * [Swarm调度策略和过滤机制](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2744) 73 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker25.jpg) 74 | * [Docker网络基础](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2745) 75 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker26.jpg) 76 | * [Docker网络模式](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2746) 77 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker27.jpg) 78 | * [灵雀云简介](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2747) 79 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker28.jpg) 80 | * [使用灵雀云命令行工具](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2748) 81 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker29.jpg) 82 | * [基于Docker进行持续集成](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2749) 83 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker30.jpg) 84 | * [网络、存储和PaaS平台](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2750) 85 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker31.jpg) 86 | * [容器OS和容器标准化](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2751) 87 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker32.jpg) 88 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | # All Vagrant configuration is done below. The "2" in Vagrant.configure 5 | # configures the configuration version (we support older styles for 6 | # backwards compatibility). Please don't change it unless you know what 7 | # you're doing. 8 | Vagrant.configure(2) do |config| 9 | # The most common configuration options are documented and commented below. 10 | # For a complete reference, please see the online documentation at 11 | # https://docs.vagrantup.com. 12 | 13 | # Every Vagrant development environment requires a box. You can search for 14 | # boxes at https://atlas.hashicorp.com/search. 15 | config.vm.box = "chef/centos-7.0" 16 | 17 | # Disable automatic box update checking. If you disable this, then 18 | # boxes will only be checked for updates when the user runs 19 | # `vagrant box outdated`. This is not recommended. 20 | # config.vm.box_check_update = false 21 | 22 | # Create a forwarded port mapping which allows access to a specific port 23 | # within the machine from a port on the host machine. In the example below, 24 | # accessing "localhost:8080" will access port 80 on the guest machine. 25 | config.vm.network "forwarded_port", guest: 4567, host: 4567 26 | config.vm.network "forwarded_port", guest: 8080, host: 8080 27 | config.vm.network "forwarded_port", guest: 5000, host: 5000 28 | config.vm.network "forwarded_port", guest: 80, host: 80 29 | config.vm.network "forwarded_port", guest: 3000, host: 3000 30 | 31 | 32 | # Create a private network, which allows host-only access to the machine 33 | # using a specific IP. 34 | config.vm.network :private_network, ip: "192.168.0.66" 35 | 36 | config.vm.hostname = "docker101vm" 37 | # Create a public network, which generally matched to bridged network. 38 | # Bridged networks make the machine appear as another physical device on 39 | # your network. 40 | # config.vm.network "public_network" 41 | 42 | # Share an additional folder to the guest VM. The first argument is 43 | # the path on the host to the actual folder. The second argument is 44 | # the path on the guest to mount the folder. And the optional third 45 | # argument is a set of non-required options. 46 | # config.vm.synced_folder "../data", "/vagrant_data" 47 | 48 | # Provider-specific configuration so you can fine-tune various 49 | # backing providers for Vagrant. These expose provider-specific options. 50 | # Example for VirtualBox: 51 | # 52 | config.vm.provider "virtualbox" do |vb| 53 | # # Display the VirtualBox GUI when booting the machine 54 | # vb.gui = true 55 | # 56 | # # Customize the amount of memory on the VM: 57 | vb.memory = "1024" 58 | vb.customize ['modifyvm', :id, '--nicpromisc1', 'allow-all'] 59 | end 60 | # 61 | # View the documentation for the provider you are using for more 62 | # information on available options. 63 | 64 | # Define a Vagrant Push strategy for pushing to Atlas. Other push strategies 65 | # such as FTP and Heroku are also available. See the documentation at 66 | # https://docs.vagrantup.com/v2/push/atlas.html for more information. 67 | # config.push.define "atlas" do |push| 68 | # push.app = "YOUR_ATLAS_USERNAME/YOUR_APPLICATION_NAME" 69 | # end 70 | 71 | # Enable provisioning with a shell script. Additional provisioners such as 72 | # Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the 73 | # documentation for more information about their specific syntax and use. 74 | # config.vm.provision "shell", inline: <<-SHELL 75 | # sudo apt-get update 76 | # sudo apt-get install -y apache2 77 | # SHELL 78 | end 79 | -------------------------------------------------------------------------------- /lesson-01/README.md: -------------------------------------------------------------------------------- 1 | # Lesson-01 课程简介及环境设置 2 | 3 | # 安装 4 | 5 | ## Clone仓库 6 | 7 | ``` 8 | 9 | [docker101vm]$ git clone https://github.com/liubin/docker101.git 10 | ``` 11 | 12 | ## 第一次启动虚拟机 13 | 14 | ``` 15 | [host]$ vagrant up 16 | [host]$ vagrant ssh 17 | ``` 18 | 19 | ## 升级系统 20 | 21 | ``` 22 | [docker101vm]$ sudo yum -y update 23 | ``` 24 | 25 | ## 重启后重新编译 VirtualBox Guest Additions 26 | 27 | ``` 28 | [docker101vm]$ sudo yum install -y gcc kernel-devel-3.10.0-229.11.1.el7.x86_64 29 | ``` 30 | 31 | ## 重启虚拟机 32 | 33 | ``` 34 | [docker101vm]$ exit 35 | [host]$ vagrant reload 36 | [host]$ vagrant ssh 37 | ``` 38 | 39 | ## 重新编译 VirtualBox Guest Additions 40 | 41 | ``` 42 | [docker101vm]$ sudo /etc/init.d/vboxadd setup 43 | ``` 44 | 45 | 再次重启即可 46 | 47 | 48 | 安装Docker(docker-engine) 49 | 50 | ``` 51 | [docker101vm]$ sudo curl -sSL https://get.docker.com/ | sh 52 | ``` 53 | 54 | 55 | 56 | ## 设置灵雀云加速 57 | 58 | ``` 59 | [docker101vm]$ sudo vi /lib/systemd/system/docker.service 60 | 61 | /usr/bin/docker daemon --registry-mirror=http://liubin.m.alauda.cn -H fd:// 62 | 63 | [docker101vm]$ sudo systemctl daemon-reload 64 | ``` 65 | 66 | 67 | ## 自启动 68 | ``` 69 | [docker101vm]$ sudo systemctl enable docker 70 | ``` 71 | 72 | ## 启动 73 | ``` 74 | [docker101vm]$ sudo systemctl start docker 75 | ``` 76 | 77 | # 参考资料 78 | 79 | 80 | - Docker主页 81 | 82 | https://www.docker.com/ 83 | 84 | - Docker 文档主页(非常有用!!!) 85 | - Docker 文档主页(非常有用!!!) 86 | - Docker 文档主页(非常有用!!!) 87 | 88 | https://docs.docker.com/ 89 | 90 | - 灵雀云镜像加速设置方法 91 | 92 | http://docs.alauda.cn/?page_id=137 93 | 94 | - March 21, 2013 Solomon gives Docker lightning talk a PyCon US 95 | 96 | https://www.youtube.com/watch?t=27&v=9xciauwbsuo 97 | 98 | - Operating-system-level virtualization implementations 99 | 100 | https://en.wikipedia.org/wiki/Operating_system-level_virtualization#Implementations 101 | 102 | - hashicorp公司主页 103 | 104 | https://hashicorp.com/ 105 | 106 | - Docker toolbox 107 | 108 | https://www.docker.com/toolbox 109 | 110 | 111 | # 视频地址 112 | 113 | * [Docker基本概念](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2720) 114 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker1.jpg) 115 | * [Docker实现原理](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2721) 116 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker2.jpg) 117 | * [Docker组件介绍](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2722) 118 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker3.jpg) 119 | * [Docker实操环境介绍](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2723) 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /lesson-01/images/docker-and-linux-kernel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-01/images/docker-and-linux-kernel.png -------------------------------------------------------------------------------- /lesson-01/images/docker-arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-01/images/docker-arch.png -------------------------------------------------------------------------------- /lesson-01/images/docker-daemon-cli.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-01/images/docker-daemon-cli.png -------------------------------------------------------------------------------- /lesson-01/images/docker-filesystem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-01/images/docker-filesystem.png -------------------------------------------------------------------------------- /lesson-01/images/docker-in-osx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-01/images/docker-in-osx.png -------------------------------------------------------------------------------- /lesson-01/images/docker-libcontainer-lxc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-01/images/docker-libcontainer-lxc.png -------------------------------------------------------------------------------- /lesson-01/images/docker-machine-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-01/images/docker-machine-logo.png -------------------------------------------------------------------------------- /lesson-01/images/docker-network.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-01/images/docker-network.png -------------------------------------------------------------------------------- /lesson-01/images/docker-solution.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-01/images/docker-solution.png -------------------------------------------------------------------------------- /lesson-01/images/docker-swarm-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-01/images/docker-swarm-logo.png -------------------------------------------------------------------------------- /lesson-01/images/docker-toolbox-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-01/images/docker-toolbox-logo.png -------------------------------------------------------------------------------- /lesson-01/images/docker-vs-vm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-01/images/docker-vs-vm.png -------------------------------------------------------------------------------- /lesson-01/keynote.md: -------------------------------------------------------------------------------- 1 | # Docker入门与实践 2 | 3 | 刘斌,软件工程师@Alauda 4 | 2015年8月 5 | 6 | 7 | # 课程简介 8 | 9 | - 目的 10 | - 对象 11 | - 内容 12 | 13 | # 对象用户 14 | 15 | - Linux 16 | - Git(GitHub) 17 | 18 | # 参考资料 19 | 20 | - 官方文档(https://docs.docker.com/) 21 | - 《第一本Docker书》 22 | 23 | # 什么是Docker 24 | 25 | - Build, Ship, Run 26 | - An open platform 27 | - For distributed applications 28 | - For developers and sysadmins 29 | - https://www.docker.com 30 | - https://www.github.com/docker/docker 31 | 32 | # 什么是Docker 33 | 34 | - 开放平台 35 | - 容器技术 36 | - 交付标准 37 | - 开发流程 38 | 39 | # Docker产生背景 40 | 41 | - 云计算技术 42 | - 软件架构 43 | - 积累的问题 44 | 45 | # 云计算技术 46 | 47 | - 虚拟化技术 48 | - IaaS(AWS) 49 | - PaaS(Heroku) 50 | - 网络技术(SDN/Open vSwitch/Overlay网络/隧道技术) 51 | 52 | # 观点 53 | 54 | - An EC2 instance is not a server—it’s a building block. 55 | - Re:Invent,Amazon’s CTO, Werner Vogels 56 | 57 | # 软件架构 58 | 59 | - SOA 60 | - 微服务 61 | - 12-Factor App 62 | - Blue-green Deployment 63 | - Golden Image 64 | 65 | # 积累问题 66 | 67 | - 依赖地狱和一致环境 68 | - Hardware 69 | - OS 70 | - Library(Version etc.) 71 | - Rails(3/4),Ruby(1.8/1.9/2.0/2.1) 72 | 73 | 74 | # 12-Factor App 75 | 76 | - Codebase 77 | - Dependencies 78 | - Config 79 | - Build, release, run 80 | - Processes 81 | - Port binding 82 | - Dev/prod parity 83 | - Logs 84 | 85 | # Docker的解决方案 86 | 87 | - 集装箱思想 88 | - 标准化(大小、运输方式等,接口统一) 89 | - 隔离(互不干扰、影响) 90 | 91 | # Docker的解决方案 92 | 93 | ![](./images/docker-solution.png) 94 | 95 | # 什么是容器? 96 | 97 | - 一组进程在独自的OS环境 98 | - 独立文件内容 99 | - 独立网络环境(hostname,IP地址等) 100 | - CPU、内存分配 101 | 102 | # 只是容器? 103 | 104 | - Docker(2013) 105 | - lmctfy(2013) 106 | - LXC(2008) 107 | - RHEL OpenVZ(2005) 108 | - Solaris Zones(2004) 109 | - FreeBSD jail(2000) 110 | - chroot(????) 111 | 112 | # 只是容器? 113 | 114 | - chroot(1979/1982) 115 | 116 | # 为什么Docker吸引人 117 | 118 | - 简单 119 | - 轻量 120 | - 隔离 121 | - 移植性 122 | - 以应用为中心 123 | - 版本化 124 | - 重用 125 | - Immutable 126 | 127 | # 简单一句话 128 | 129 | - 从阳春白雪,到下里巴人 130 | - 从专业运维、SA专家,到前端、设计师 131 | 132 | # 和虚拟机相比 133 | 134 | ![](./images/docker-vs-vm.png) 135 | 136 | # 和虚拟机相比 137 | 138 | - 实现原理 139 | - 启动时间 140 | - 可启动实例数量 141 | - overhead 142 | - 安全性(隔离) 143 | - 磁盘空间 144 | 145 | # Docker实现原理 146 | 147 | - 核心Linux内核功能 148 | - Control Groups(cgroups) 149 | - Namespace 150 | - iptables 151 | - Union File System 152 | 153 | # 安全相关内核功能 154 | 155 | - Kernel Capability 156 | - 对进程持有的特权进行细粒度管理的机制 157 | - 系统时间,内核模块,硬件设备 158 | - SELinux(Security-Enhanced Linux/RedHat系Linux) 159 | - Apparmor(简单/Debian/Ubuntu) 160 | 161 | # cgroups 162 | 163 | - Control groups 164 | - 按资源划分等级的不同组内 165 | - 共享硬件 166 | - 对资源进行限制 167 | - 记账 168 | - 伪文件系统的实现方式 169 | 170 | # cgroups 171 | 172 | - blkio: 块设备读写限制(Read <= N bytes/sec) 173 | - cpu: 对CPU调度器的限制 174 | - cpuset: 多核下对CPU访问的控制 175 | - cpuacct: CPU accounting controller 176 | - devices: 对设备的控制 177 | - freezer:处理的暂停和恢复 178 | - memory: 控制内存资源的使用 179 | - net_cls: 使用等级识别符(classid)标记网络数据包,可允许 Linux 流量控制程序(tc)识别从具体 cgroups 中生成的数据包。 180 | - net_prio: 对不同网络接口通信的优先级别的设置 181 | 182 | 183 | # Namespaces 184 | 185 | - pid: 进程(PID)隔离(2.6.24) 186 | - net: 网络隔离(2.6.26) 187 | - ipc: IPC隔离,POSIX消息队列,共享内存(2.6.19) 188 | - mnt: 挂载点隔离(2.4.19) 189 | - uts: hostname,NIS域名(UTS: Unix Timesharing System)(2.6.19) 190 | - user: 用户隔离(3.8) 191 | 192 | # Docker适用场景 193 | 194 | - 开发 195 | - 测试 196 | - 部署 197 | - CI/CD 198 | - PaaS/CaaS 199 | - 只有想不到,没有做不到 200 | - 还有人用来装Eclipse呢 201 | 202 | # Docker将会给这些领域带来影响 203 | 204 | - Software Development 205 | - Deploy & Delivery 206 | - DevOps 207 | 208 | # Docker带来的收益 209 | 210 | - 快速交付(交付标准) 211 | - 轻松部署 212 | - 快速缩、扩容 213 | - 提高资源利用率(高密度、满负荷) 214 | - 提升软件工程师满意度 215 | 216 | # Docker历史 217 | 218 | - 优秀的产品背后都有一家伟大的公司 219 | - docCloud(YCombinator),2013年1月内部项目 220 | - 2013年3月,在PyCon US首次公开 221 | - 2013/3/27 Docker 0.1 222 | - 2014/6 Docker 1.0 223 | - 几乎每月一个版本 224 | - 2015年8月,Docker 1.8发布 225 | - 2014.7 C轮融资4000万美元 226 | - 2015.4 D轮融资9500万美元 227 | 228 | # 支持平台 229 | 230 | - Linux 231 | - Boot2Docker(Windows 、 OS X) 232 | - Windows native 233 | 234 | # Docker 组件 235 | 236 | - Docker Engine 或 “Docker” 237 | - 创建和运行Docker容器,运行平台。 238 | - Docker Hub 239 | - 托管的Registry,镜像托管服务,无需安装,只需要注册一个账号。 240 | - Docker Registry 241 | - 开源的Docker镜像分发服务(存储、下载)。 242 | 243 | 244 | # Docker 组件 245 | 246 | - Docker Machine 247 | - 本地或者云端自动容器环境provisioning工具。 248 | - Docker Compose 249 | - 多容器应用管理 250 | - Docker Swarm 251 | - 容器集群和调度管理工具 252 | 253 | # Docker 组件 254 | 255 | - Kitematic 256 | - 桌面GUI管理程序 257 | - Docker Toolbox 258 | - 替代Boot2Docker 259 | 260 | # Docker 组件 261 | 262 | - Docker Trusted Registry(DTR) 263 | - 私有专用镜像Registry。 264 | - Docker Subscription 265 | - Docker订购,增值服务; 266 | - 在整个部署、分发的生命周期提供帮助 267 | - 包括DTR 268 | - 部署到公有或者私有云 269 | 270 | # 我们不会讲 271 | 272 | - Docker ToolBox/Kitematic: 有了本课程基础,应对Kitematic应该小事一桩 273 | - DTR: 我们会讲Registry 274 | - Docker Subscription: 275 | - 1. 我们会讲 Registry 276 | - 2. 都花钱买Subscription了,就享受服务吧 277 | 278 | # Docker Engine架构 279 | 280 | - C/S结构 281 | - Remote API(RESTful) 282 | - TLS支持 283 | 284 | ![](./images/docker-arch.png) 285 | 286 | # Docker in Linux 287 | 288 | ![](./images/docker-daemon-cli.png) 289 | 290 | # Libcontainer 291 | 292 | - Container format 293 | - Execution driver 294 | - 将cgroups,Namespace,Union FS集成到一起使用 295 | 296 | ![](./images/docker-libcontainer-lxc.png) 297 | 298 | # Docker Engine核心概念 299 | 300 | - Docker镜像(image) 301 | - Docker容器(containers) 302 | - Docker Registry 303 | 304 | # 镜像 305 | 306 | - 文件系统 307 | - 只读、静态 308 | - 层(Layer) 309 | - 父子关系(Parent Image) 310 | - 基础镜像(Base Image) 311 | - ID(64字符,256bit存储) 312 | 313 | # 容器 - Container 314 | 315 | - 创建、运行和退出 316 | - ID(和镜像ID类似) 317 | 318 | ![](./images/docker-filesystem.png) 319 | 320 | # Registry 321 | 322 | - 托管镜像仓库(repositories of images) 323 | - Registry API 324 | - Docker Hub和私有Registry 325 | - 码头上的仓库 326 | 327 | # 课程演习环境 328 | 329 | - Vagrant 330 | - CentOS 7 331 | - Docker 1.7.1 332 | - 灵雀云(alauda.cn) 333 | 334 | # Docker For Non-Linux 335 | 336 | - Boot2Docker 337 | - Toolbox 338 | 339 | # Docker in Non-Linux 340 | 341 | ![](./images/docker-in-osx.png) 342 | 343 | # Docker Toolbox (Docker 1.8) 344 | 345 | - Docker Client 346 | - Docker Machine 347 | - Docker Compose (Mac only) 348 | - Docker Kitematic 349 | - VirtualBox 350 | 351 | ![](./images/docker-toolbox-logo.png) 352 | 353 | # VirtualBox和Vagrant 354 | 355 | - 虚拟机 356 | - 虚拟机管理软件 357 | - hashicorp 358 | - Serf/Consul/Packer等工具 359 | 360 | # Vagrant 361 | 362 | - vagrant init chef/centos-7.0 363 | - vagrant up 364 | - vagrant ssh 365 | 366 | # Vagrant 367 | 368 | - 下载centos7镜像:http://pan.baidu.com/s/1kT7u5oF 369 | - vagrant box add chef/centos-7.0 opscode_centos-7.0_chef-provisionerless.box 370 | - 执行上一页命令 371 | 372 | # 不必一切从头开始 373 | 374 | - git clone https://github.com/liubin/docker101 375 | 376 | # Vagrantfile 377 | 378 | - box 379 | - forwarded_port 380 | - synced_folder 381 | 382 | # 安装Docker 383 | 384 | - 64位Linux 385 | - 内核3.10 386 | 387 | # 安装Docker 388 | 389 | - $ sudo yum update 390 | - $ curl -sSL https://get.docker.com/ | sh 391 | - $ sudo systemctl enable docker 392 | - $ sudo systemctl start docker 393 | - $ sudo docker -v 394 | - Docker version 1.8.1, build d12ea79 395 | 396 | # 设置镜像加速 397 | 398 | - 灵雀云(https://console.alauda.cn) 399 | - --registry-mirror=http://liubin.m.alauda.cn 400 | 401 | # 答疑 402 | 403 | - https://github.com/liubin/docker101 404 | - Alauda社区 405 | 406 | # 课后作业 407 | 408 | - 浏览官方文档 409 | - 安装Docker 410 | - 注册alauda.cn账户 411 | 412 | -------------------------------------------------------------------------------- /lesson-02/README.md: -------------------------------------------------------------------------------- 1 | # lesson-2 运行Docker容器 2 | 3 | 4 | # jq 5 | 6 | ``` 7 | # docker inspect centos | jq ".[0].Config.Cmd" 8 | [ 9 | "/bin/bash" 10 | ] 11 | 12 | # docker inspect centos | jq ".[0].Config.Entrypoint" 13 | null 14 | 15 | ``` 16 | 17 | # 运行Docker 18 | 19 | ## 1. 设置灵雀云加速 20 | 21 | ``` 22 | [docker101vm]$ sudo vi /lib/systemd/system/docker.service 23 | 24 | /usr/bin/docker daemon --registry-mirror=http://liubin.m.alauda.cn -H fd:// 25 | 26 | [docker101vm]$ sudo systemctl daemon-reload 27 | [docker101vm]$ sudo systemctl restart docker 28 | ``` 29 | 30 | ## 2. 后台容器 31 | 32 | shell 1: 33 | 34 | ``` 35 | docker run --name web -d -p 5000:5000 training/webapp python app.py 36 | docker logs -f web 37 | ``` 38 | 39 | shell 2: 40 | 41 | ``` 42 | curl localhost:5000 43 | ``` 44 | 45 | ## attach 46 | 47 | ``` 48 | docker run -d --name top1 centos top -b 49 | 50 | docker attach top1 51 | ctrl-c 52 | 53 | docker run -d --name top2 centos top -b 54 | 55 | docker attach --sig-proxy=false top2 56 | ctrl-c 57 | 58 | docker ps -a 59 | 60 | ``` 61 | 62 | ## stop和kill的区别 63 | 64 | ``` 65 | docker run --name web -d -P training/webapp python app.py 66 | docker stop web 67 | docker rm web 68 | 69 | docker run --name web -d -P training/webapp python app.py 70 | docker kill web 71 | docker rm web 72 | 73 | docker run --name web -d -P training/webapp python app.py 74 | docker kill -s SIGTERM 75 | 76 | docker run --name web -d -P training/webapp python app.py 77 | docker kill -s SIGKILL 78 | 79 | ``` 80 | 81 | ## docker events 82 | 83 | ### shell 1 84 | 85 | ``` 86 | docker events 87 | ``` 88 | 89 | ### shell 2 90 | 91 | ``` 92 | # Start a new container 93 | 94 | job=$(docker run -d centos /bin/sh -c "while true; do echo Hello world; sleep 1; done") 95 | 96 | docker stop $job 97 | 98 | docker start $job 99 | 100 | docker restart $job 101 | 102 | docker kill $job 103 | 104 | docker rm $job 105 | ``` 106 | 107 | ### shell 1 108 | 109 | ``` 110 | docker events -f 'event=stop' 111 | ``` 112 | 113 | ### shell 2 114 | 115 | 同上。 116 | 117 | ## docker restart 118 | 119 | shell 1: 120 | 121 | ``` 122 | docker events 123 | ``` 124 | 125 | shell 2 126 | 127 | ``` 128 | docker run -d --name alwayrestart --restart=always centos /bin/sh -c "while true; do echo Hello world; sleep 2; exit -1; done" 129 | docker logs -f alwayrestart 130 | ``` 131 | 132 | ## docker diff 133 | 134 | ``` 135 | docker run --name container-diff centos sh -c 'echo "hello diff"> /test.txt' 136 | 137 | docker diff container-diff 138 | 139 | ``` 140 | 141 | ## docker run -v / -e 142 | 143 | ``` 144 | docker run -it -v `pwd`/test-data:/test_data -e DB_HOST=mysql centos bash 145 | ``` 146 | 147 | 在容器内 148 | 149 | ``` 150 | # env 151 | # echo "text from container" > /test_data/hehe.txt 152 | # exit 153 | ``` 154 | 155 | 在主机内 156 | 157 | ``` 158 | cat ./test-data/hehe.txt 159 | ``` 160 | 161 | # docker log存储 162 | 163 | shell 1: 164 | 165 | ``` 166 | id=$(docker run --name web -d -p 5000:5000 training/webapp python app.py) 167 | tail -f /var/lib/docker/containers/$id/$id-json.log 168 | 169 | ``` 170 | 171 | shell 2: 172 | 173 | ``` 174 | curl localhost:5000 175 | ``` 176 | 177 | # 添加dummy网络设备 178 | 179 | ``` 180 | # docker run -it --rm centos ip link add dummy0 type dummy 181 | RTNETLINK answers: Operation not permitted 182 | # docker run -it --rm --cap-add=NET_ADMIN centos ip link add dummy0 type dummy 183 | ``` 184 | 185 | # PID=host 186 | 187 | ``` 188 | docker run -it --pid=host centos bash 189 | 190 | ``` 191 | 192 | # net=host 193 | 194 | ``` 195 | docker run -it --net=host centos bash 196 | ``` 197 | 198 | # 视频地址 199 | 200 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker4.jpg) 201 | * [什么是Docker容器](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2724) 202 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker5.jpg) 203 | * [深入Docker容器](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2725) 204 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker6.jpg) 205 | * [Docker容器的生命周期管理](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2726) 206 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker7.jpg) 207 | -------------------------------------------------------------------------------- /lesson-02/keynote.md: -------------------------------------------------------------------------------- 1 | # Docker入门与实践 2 | 3 | Lesson-02 运行Docker容器 4 | 刘斌@Alauda 5 | 2015年8月 6 | 7 | # 本节概要 8 | 9 | - docker命令的两个角色 10 | - 理解容器构造 11 | - 管理容器生命周期 12 | - docker run命令的用法 13 | 14 | # docker命令 15 | 16 | - 一个命令,两个角色 17 | - daemon: docker daemon 18 | - client: docker run/ps/rm/images 19 | - docker -D? 20 | 21 | # Docker daemon(Server) 22 | 23 | - -H=[],监听接口(damain socket或者IP/端口) 24 | - unix:///var/run/docker.sock 25 | - -H tcp://host:2375 26 | - --tls=true|false 27 | - 《第一本Docker书》第8.5节 28 | - fd: Systemd socket activation 29 | 30 | # Docker Daemon参数 31 | 32 | - 网络、安全、日志等 33 | - -e, --exec-driver="native" 34 | - -s, --storage-driver="" 35 | - 存储驱动AUFS/device mapper/btrfs/zfs/overlay 36 | 37 | # Docker execdriver 38 | 39 | - libcontainer 40 | - lxc 41 | 42 | ![](../lesson-01/images/docker-libcontainer-lxc.png) 43 | 44 | # Docker daemon(Server) 45 | 46 | - $ sudo systemctl status docker 47 | - $ sudo systemctl start docker 48 | - $ sudo systemctl stop docker 49 | - $ sudo systemctl restart docker 50 | - $ sudo systemctl enable docker 51 | 52 | # DOCKER_HOST环境变量 53 | 54 | - docker -H tcp://0.0.0.0:2375 ps 55 | - export DOCKER_HOST="tcp://0.0.0.0:2375" && docker ps 56 | 57 | # 设置灵雀云加速 58 | 59 | ``` 60 | [docker101vm]$ sudo vi /lib/systemd/system/docker.service 61 | 62 | /usr/bin/docker daemon --registry-mirror=http://liubin.m.alauda.cn -H fd:// 63 | 64 | [docker101vm]$ sudo systemctl daemon-reload 65 | ``` 66 | 67 | # 演示 1 68 | 69 | - 通过IP地址连接远程Docker 70 | - docker -H tcp://0.0.0.0:2375 pull ubuntu 71 | 72 | # 启动容器 73 | 74 | - docker run [OPTIONS] IMAGE[:TAG|@DIGEST] [COMMAND] [ARG...] 75 | 76 | # 演示 2 77 | 78 | - 启动我们的第2个容器 79 | - $ sudo docker run -it centos bash 80 | 81 | # 演示 2:容器内部 82 | 83 | - [root@e757c235c60c /]# 84 | - hostname 85 | - ip addr show eth0 86 | - mount 87 | - ps -ef 88 | - mount 89 | - exit 90 | - docker ps -a 91 | 92 | # 演示 3:容器/镜像 ID 93 | 94 | - 64位 95 | - 容器 96 | - 镜像/镜像层 97 | - 长形UUID(64位) 98 | - 短形UUID(12位) 99 | - 1位? 100 | 101 | # 容器命名 102 | 103 | - name:cocky_curie(scientists and hackers) 104 | - docker run --name 105 | 106 | # Tips: 如何获得容器ID? 107 | 108 | - cid=$(docker run --name name1 -d -P --cidfile=/tmp/cid.lock training/webapp python app.py) 109 | - docker stop $cid 110 | - --cidfile="some/path" 111 | 112 | # 容器的生命周期 113 | 114 | - 创建、启动(docker create/run/restart) 115 | - 停止(stop、kill区别?) 116 | - 销毁(rm) 117 | 118 | # 前台容器和后台容器 119 | 120 | - Foreground/Detached (-d) 121 | - sudo docker run -it centos bash 122 | 123 | # 前台容器 124 | 125 | - 启动容器内进程,并将当前控制台attach到该进程的标准输入、输出和错误。 126 | - -t:分配一个伪终端(TTY) 127 | - -i:保持STDIN打开 128 | - -it:交互式控制台(Shell) 129 | 130 | # 后台容器 131 | 132 | ```bash 133 | docker run --name web -d -P training/webapp python app.py 134 | docker port web 135 | ``` 136 | 137 | # 后台容器 138 | 139 | - -d: 后台运行,无前台输入输出交互 140 | - -P: 暴露所有端口 141 | - -p: 精确指定端口 142 | 143 | # docker attach 144 | 145 | - attach 到一个Detached的容器上 146 | 147 | 148 | # docker attach 149 | 150 | - docker attach [OPTIONS] CONTAINER 151 | - --no-stdin=false 152 | - --sig-proxy=true 153 | - detach: CTRL-p CTRL-q (for a quiet exit) 154 | - detach: CTRL-c if --sig-proxy == false 155 | - SIGINT: CTRL-c if --sig-proxy == true(默认) 156 | 157 | 158 | # docker attach 159 | 160 | - 演示5 161 | 162 | # stop/kill 163 | 164 | - stop,SIGTERM,超过-t(10s)则SIGKILL 165 | - kill,SIGKILL 166 | - kill -s, --signal="SIGKILL" 167 | 168 | # 常用容器命令 169 | 170 | - docker stop/kill 171 | - docker ps -a|-n --no-trunc 172 | - docker rm 173 | 174 | # Tips 自动删除停止的容器 175 | 176 | - docker run --rm 自动清除容器 177 | - 和选项 -d 不兼容 178 | 179 | # 容器网络设置 180 | 181 | - --dns=[] 182 | - --mac-address="" 183 | - --add-host="" 184 | - --net="bridge" 185 | 186 | # --net选项 187 | 188 | - bridge 189 | - none 190 | - container: 191 | - host 192 | 193 | # Tips 如何修改容器内的/etc/hosts文件? 194 | 195 | ```bash 196 | docker run -it --add-host db-server:10.10.0.100 197 | ``` 198 | 199 | # 演示 200 | 201 | - 使用host模式 202 | - 检查网络设置 203 | - /etc/hosts 204 | - /etc/resolve.conf 205 | - /etc/hostname 206 | - --add-host测试 207 | 208 | 209 | # docker events 210 | 211 | - docker events [OPTIONS] 212 | - create, destroy, die, export, kill, oom, pause, restart, start, stop, unpause 213 | - untag, delete 214 | - 指定时间段和过滤器 215 | - 演示6 216 | 217 | # 指定时间条件 218 | 219 | - --since="" 220 | - --until="" 221 | - docker events --since 1378216169 222 | - docker events --since '2013-09-03' 223 | - docker events --since '2013-09-03T15:49:29' 224 | 225 | # 指定filter 226 | 227 | - -f / --filter 228 | - container 229 | - event 230 | - image 231 | - AND / OR 232 | 233 | # 指定filter 234 | 235 | - docker events -f 'event=stop' 236 | - docker events -f 'image=ubuntu:14.04' 237 | - docker events -f 'container=xx' -f 'container=yy' 238 | - docker events -f 'container=xx' -f 'event=stop' 239 | 240 | # restart机制 241 | 242 | - none 243 | - on-failure[:max-retries] 244 | - always 245 | - 每次重试间隔时间都翻倍,直到stop或rm -f 246 | - 演示7 247 | 248 | # 其他一些docker命令 249 | 250 | - docker rename/top/cp 251 | - docker pause CONTAINER 252 | - docker unpause CONTAINER 253 | - docker diff 254 | 255 | # docker create 256 | 257 | - docker create [OPTIONS] IMAGE [COMMAND] [ARG...] 258 | - then docker start 259 | - 状态:created. 260 | 261 | # docker create 用武之地 262 | 263 | ```bash 264 | docker create -v /data --name data centos 265 | 240633dfbb98128fa77473d3d9018f6123b99c454b3251427ae190a7d951ad57 266 | docker run --rm --volumes-from data centos ls -la /data 267 | total 8 268 | drwxr-xr-x 2 root root 4096 Dec 5 04:10 . 269 | drwxr-xr-x 48 root root 4096 Dec 5 04:11 .. 270 | ``` 271 | 272 | # 常用选项 273 | 274 | - 在镜像中指令有关 275 | - -v 276 | - -e 277 | - -p 278 | - -P 279 | 280 | # ENTRYPOINT 281 | 282 | - --entrypoint="" 283 | - docker inspect centos | jq ".[0].Config.Entrypoint" 284 | 285 | # EXPOSE 286 | 287 | - Dockerfile里唯一对网络设置选项 288 | - -P或-p 289 | - -p 5000 290 | - -p 6000:6000 291 | - -p 127.0.0.1:7000:7000 292 | - -p 127.0.0.1::7000 293 | 294 | # ENV 295 | 296 | - 预设: HOME/HOSTNAME/PATH/TERM 297 | - --link 298 | - -e "deep=purple" 299 | 300 | # VOLUME 301 | 302 | - -v=[] [host-dir:]container-dir[:rw|ro] 303 | - --volumes-from="" 304 | 305 | # 演示8 306 | 307 | - 见 README.md 308 | 309 | # USER 310 | 311 | - 默认为root 312 | - -u="": Username or UID 313 | 314 | # WORKDIR 315 | 316 | - -w="" 317 | 318 | 319 | # Logging驱动 320 | 321 | - 容器可以指定logging驱动 322 | - --log-driver=VALUE 323 | - none 324 | - json-file(默认,docker logs可用) 325 | - syslog 326 | - journald 327 | - gelf: Graylog Extended Log Format (GELF) 328 | - fluentd 329 | 330 | # 演示9 331 | 332 | - 查看log 333 | - /var/lib/docker/containers 334 | - 容器停止后的log 335 | - 见 README.md 336 | 337 | # 对容器进行资源限制-Memory 338 | 339 | - -m, --memory="": 格式 (单位为b/k/m/g) 340 | - --memory-swap="": 内存总量限制(memory+swap,单位同上) 341 | - --oom-kill-disable=true|false 342 | 343 | # 对容器进行资源限制-Memory 344 | 345 | - -m 300M --memory-swap -1 346 | - -m 300M (--memory-swap 600M) 347 | - 全部内存 = 2 * m,swap = m 348 | - -m 300M --memory-swap 1G 349 | 350 | # 对容器进行资源限制-Memory 351 | 352 | - -m 100M --oom-kill-disable 353 | - --oom-kill-disable <- 危险行为 354 | 355 | # 对容器进行资源限制-CPU 356 | 357 | - -c, --cpu-shares=0: CPU shares (相对权重) 358 | - --cpu-period=0: 限制 CPU完全公平调度程序 (Completely Fair Scheduler)时间 359 | - --cpu-quota=0: 限制 CPU CFS用量 360 | - --cpuset-cpus="": 可用CPU的核(0-3, 0,1) 361 | - --cpuset-mems="": 可利用的Memory节点 (0-3, 0,1),NUMA系统可用 362 | - 非一致性内存访问 NUMA(Non-Uniform Memory Access Architecture) 363 | - NUMA = SMP(对称多处理) + MPP(大规模并行处理) 364 | - 每个节点都有独立的CPU+内存,甚至I/O 365 | 366 | # 对容器进行资源限制-CPU share 367 | 368 | - 所有容器的默认CPU周期(cycles)权重为1024 369 | - 通过-c 或 --cpu-shares 设置为大于2的值 370 | - 多个容器按比例分配CPU 371 | 372 | # 对容器进行资源限制-CPU quota 373 | 374 | - 选项 --cpu-quota 用来对容器的CPU使用做出限制 375 | - 默认值0表示可以使用100%的CPU 376 | 377 | # 对容器进行资源限制-CPU period 378 | 379 | - 默认完全公平调度程序CFS(Completely Fair Scheduler)周期为100ms 380 | - 通过--cpu-period 可以限制容器的CPU使用 381 | - 单位:microseconds,百万分之一,微秒 382 | - 通常和--cpu-quota一起工作 383 | - --cpu-period=50000 --cpu-quota=25000 -> 50% CPU 384 | 385 | # 对容器进行资源限制-CPU set 386 | 387 | - 指定运行所在CPU 388 | - --cpuset-cpus="1,3" ... 389 | - --cpuset-cpus="0-2" ... 390 | 391 | # 对容器进行资源限制-Block I/O 392 | 393 | - --blkio-weight 394 | - 设置I/O权重,取值范围为10~1000 395 | - 容器默认I/O权重为500 396 | - $ docker run --blkio-weight 300 397 | 398 | # 和Namespace相关的一些参数 399 | 400 | - PID 401 | - UTS 402 | - IPC 403 | 404 | # PID 405 | 406 | - --pid="",设置容器的PID namespace 407 | - --pid=host 408 | 409 | # UTS 410 | 411 | - --uts="",设置UTS namespace 412 | - 'host' 413 | - 容器名随host而变 414 | - 在容器中修改host的主机名 415 | 416 | # IPC 417 | 418 | - --ipc="",设置容器的IPC模式 419 | - container: 420 | - host 421 | - 演示10 422 | 423 | # Linux capabilities 424 | 425 | - 默认Docker容器没有特权“unprivileged” 426 | - --privileged 允许容器访问所有设备(device) 427 | - 或修改AppArmor/SELinux的配置 428 | - 精细控制(--cap-add/--cap-drop) 429 | - --device 430 | - --lxc-conf 431 | - docker run --device=/dev/snd:/dev/snd ... 432 | 433 | # Linux capabilities示例 434 | 435 | - SETPCAP: 修改进程 436 | - SYS_MODULE: 加载/卸载内核模块 437 | - SYS_ADMIN:系统管理 438 | - SYS_TIME: 修改系统时间 439 | - NET_ADMIN: 网络管理操作 440 | - KILL: 跳过权限发送signal 441 | - SETGID/SETUID:设置UID/GID 442 | - SYSLOG:使用SYSLOG 443 | - CHOWN:修改属主 444 | 445 | 446 | # 课后作业 447 | 448 | - 下载centos仓库 449 | - docker run -it centos bash 450 | - docker ps -a 451 | - docker rm 452 | - 尝试docker run的各种选项 453 | 454 | 455 | 456 | 457 | 458 | -------------------------------------------------------------------------------- /lesson-03/README.md: -------------------------------------------------------------------------------- 1 | # lesson-3 理解Docker镜像 2 | 3 | # 常用操作 4 | 5 | ## 1. pull/push 6 | 7 | ``` 8 | docker search wordpress | head -10 9 | 10 | docker pull wordpress 11 | 12 | docker images 13 | 14 | docker images wordpress 15 | 16 | docker history wordpress 17 | 18 | docker inspect wordpress 19 | 20 | docker inspect -f "{{.Config}}" wordpress 21 | 22 | docker inspect wordpress | jq ".[0].Config" 23 | 24 | docker inspect wordpress | jq ".[0].Config.Cmd" 25 | 26 | docker inspect wordpress | jq ".[0].Config.Entrypoint" 27 | 28 | 29 | docker login index.alauda.cn 30 | 31 | docker tag busybox index.alauda.cn/liubin/test 32 | 33 | docker images 34 | 35 | docker push index.alauda.cn/liubin/test 36 | 37 | docker rmi index.alauda.cn/liubin/test 38 | 39 | ``` 40 | 41 | ## 2. 通过commit构建镜像 42 | 43 | ``` 44 | docker run -it centos bash 45 | ``` 46 | 47 | 进入容器安装Nginx 48 | 49 | 50 | ``` 51 | # rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm 52 | # yum install -y nginx 53 | 54 | # vi /etc/nginx/nginx.conf 55 | add "daemon off;" 56 | 57 | ``` 58 | 59 | 退出容器后,提交定制容器 60 | 61 | ``` 62 | cid=$(docker ps -lq) 63 | 64 | docker commit --change="CMD [\"/usr/sbin/nginx\"]" --message="Docker101 Nginx image" --author="bin liu" $cid liubin/nginx 65 | 66 | ``` 67 | 68 | 可以使用`docker inspect`命令来查看新创建的镜像的详细信息 69 | 70 | 71 | ``` 72 | docker inspect liubin/nginx 73 | 74 | ``` 75 | 76 | 启动容器并确认 77 | 78 | ``` 79 | docker run --name nginx -d -p 80:80 liubin/nginx 80 | ``` 81 | 82 | ## 3. save 83 | 84 | ``` 85 | mkdir /tmp/bb && cd /tmp/bb 86 | 87 | docker save --output busybox.tar busybox 88 | 89 | tar xf busybox.tar 90 | 91 | ls 92 | 93 | ``` 94 | 95 | # 存储 96 | 97 | ## 检验AUFS镜像存储 98 | 99 | 100 | ``` 101 | # docker run -it centos bash 102 | 103 | [container]# echo "hello world" > /root/test.txt 104 | 105 | [container]# echo "hello world" >> /etc/redhat-release 106 | [container]# rm /etc/bashrc 107 | 108 | [container]# exit 109 | 110 | # docker diff $c 111 | 112 | # cd /var/lib/docker/aufs/diff/$c 113 | # pwd 114 | /var/lib/docker/aufs/diff/ee0e5435dc4cb670517c973e88f9d66d19fb617305463b982482ecb56c12e4ce 115 | 116 | # ls 117 | 118 | # ls root/ 119 | test.txt 120 | 121 | # cat root/test.txt 122 | 123 | hello world 124 | ``` 125 | 126 | ## 检验DM镜像存储 127 | 128 | ### 常用命令 129 | 130 | ``` 131 | docker info 132 | 133 | losetup 134 | 135 | dmsetup ls 136 | 137 | docker run -d centos /bin/sh -c "while true; do echo Hello world; sleep 1; done" 138 | 139 | dmsetup ls 140 | 141 | ``` 142 | 143 | 启动一个容器后 144 | 145 | ``` 146 | [root@docker101vm ~]# docker run centos /bin/bash -c 'echo "hello world" > /root/test.txt' 147 | 148 | [root@docker101vm ~]# c=$(docker ps -alq --no-trunc) 149 | 150 | 151 | [root@docker101vm ~]# cat /var/lib/docker/devicemapper/metadata/$c | jq . 152 | 153 | { 154 | "device_id": 579, 155 | "size": 10737418240, 156 | "transaction_id": 1089, 157 | "initialized": false 158 | } 159 | 160 | 161 | [root@docker101vm ~]# device_id=579 162 | [root@docker101vm ~]# size=10737418240 163 | [root@docker101vm ~]# pool=docker-253:1-134414442-pool 164 | 165 | [root@docker101vm ~]# dmsetup ls 166 | 167 | [root@docker101vm ~]# dmsetup create myvol --table "0 $(($size / 512)) thin /dev/mapper/$pool $device_id" 168 | 169 | [root@docker101vm ~]# dmsetup ls 170 | [root@docker101vm ~]# mkdir /mnt-test 171 | [root@docker101vm ~]# mount /dev/mapper/myvol /mnt-test 172 | [root@docker101vm ~]# ls /mnt-test/ 173 | id lost+found rootfs 174 | [root@docker101vm ~]# cat /mnt-test/rootfs/root/test.txt 175 | hello world 176 | 177 | 178 | [root@docker101vm ~]# mount | grep test 179 | /dev/mapper/myvol on /mnt-test type ext4 (rw,relatime,seclabel,stripe=16,data=ordered) 180 | [root@docker101vm ~]# umount /mnt-test 181 | [root@docker101vm ~]# mount | grep test 182 | [root@docker101vm ~]# dmsetup remove myvol 183 | [root@docker101vm ~]# 184 | 185 | ``` 186 | 187 | # 视频地址 188 | 189 | * [认识Docker镜像](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2727) 190 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker8.jpg) 191 | * [手工构建Docker镜像](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2728) 192 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker9.jpg) 193 | 194 | -------------------------------------------------------------------------------- /lesson-03/images/dm-block-mapping.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-03/images/dm-block-mapping.png -------------------------------------------------------------------------------- /lesson-03/images/dm-remap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-03/images/dm-remap.png -------------------------------------------------------------------------------- /lesson-03/images/dm-snapshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-03/images/dm-snapshot.png -------------------------------------------------------------------------------- /lesson-03/keynote.md: -------------------------------------------------------------------------------- 1 | # Docker入门与实践 2 | 3 | Lesson-03 理解Docker镜像 4 | 刘斌@Alauda 5 | 2015年8月 6 | 7 | # 本节概要 8 | 9 | - 镜像构造 10 | - 管理镜像 11 | - 手工构建镜像 12 | - Docker存储原理 13 | 14 | # 什么是Docker镜像 15 | 16 | - 容器的模板 17 | - 分层 18 | - manifest(json) + layers 19 | - layer: tar包 20 | 21 | ![](../lesson-01/images/docker-filesystem.png) 22 | 23 | # 分层的优势 24 | 25 | - 轻量(磁盘空间) 26 | - 缓存,提高构建速度 27 | 28 | # Repository 29 | 30 | - 存放一组镜像的仓库 31 | - 有一个名字 32 | - 一个镜像可以属于多个仓库 33 | - docker commit 34 | - docker build -t 35 | - docker tag 36 | 37 | # 仓库名称 38 | 39 | - [registry[:port]/][user_name/]repository_name:version_tag 40 | - 默认index.docker.io:80 41 | 42 | 43 | # 拉取和推送镜像 44 | 45 | - docker search 46 | - docker pull 47 | - docker push 48 | 49 | # 查看Docker镜像 50 | 51 | - docker images 52 | - REPO/TAG/ID 53 | - docker history 54 | - docker inspect 55 | - tag 56 | - docker rmi 57 | 58 | # 演示1 59 | 60 | - docker login 61 | - docker pull 62 | - docker tag 63 | - docker push 64 | 65 | # 构建镜像 66 | 67 | - 必要性 68 | - 方式:commit,Dockerfile,从0开始 69 | - 优缺点:Dockerfile > commit> 从0开始 70 | 71 | # 通过docker commit命令构建镜像 72 | 73 | - docker run -it base bash 74 | - # yum update && yum install xxx && exit 75 | - docker commit 76 | 77 | # 演示2 78 | 79 | - 创建nginx镜像 80 | 81 | # docker commit 参数 82 | 83 | - -m --message 84 | - -a --author 85 | - -c --changes 86 | 87 | # commit -c可覆盖参数 88 | 89 | - CMD、ENTRYPOINT 90 | - ENV 91 | - EXPOSE 92 | - ONBUILD 93 | - USER 94 | - VOLUME 95 | - WORKDIR 96 | 97 | # 共享镜像 98 | 99 | - 镜像存储 100 | - 官方 101 | - 免费+收费 102 | - 或私有Registry 103 | 104 | # 拷贝到其他机器 105 | 106 | - Docker iamge = tar文件 107 | - export/import 108 | - save/load 109 | 110 | # export/import 111 | 112 | - export:整个mount,将rootfs打成一个tar包 113 | - import:tar包解包而已 114 | - 镜像层级关系和metadata丢失 115 | - 不能共享层文件,占用大量磁盘空间 116 | - 能导入物理机或者虚拟机的rootfs 117 | 118 | # save/load 119 | 120 | - 按镜像层分别打tar包 121 | - 一层层mount,打包 122 | - 先打base 123 | - mount下一层,打包差分 124 | - 记录metadata 125 | - 将结果再打成一个tar包 126 | 127 | # 演示3 128 | 129 | - save导出镜像 130 | - 解压查看分层 131 | 132 | # Docker存储引擎 133 | 134 | - CoW 135 | - AUFS 136 | - Device Mapper 137 | - BTRFS 138 | - overlay(fs) 139 | - VFS 140 | - ZFS 141 | 142 | # CoW 143 | 144 | - Copy on Write 145 | - Copy only (when) Write 146 | - Memory(并发编程中犹如内存管理的GC) 147 | - Storage 148 | 149 | # AUFS 150 | 151 | - Advanced(Another) Union FS 152 | - Ubuntu/Debian 153 | - 没进内核主线 154 | - dotCloud从2008年就开始用 155 | - 适合高密度的类PaaS场景 156 | 157 | # AUFS原理 158 | 159 | - 由多个分支按一定顺序组合 160 | - 每个只是一个普通文件夹 161 | - 若干只读分支和一个读写分支(顶层) 162 | 163 | # AUFS原理-读写文件 164 | 165 | - 读取时从顶层开始查找文件 166 | - 找到则打开 167 | - 写入时如果在顶层找到目标文件,则打开 168 | - 否则继续向下找 169 | - 如果找到,则拷贝到顶层,开始写入 170 | - 找不到则在顶层创建文件并写入 171 | 172 | # AUFS原理-删除文件 173 | 174 | - 创建一个whiteout文件表示删除 175 | 176 | # 演示4 177 | 178 | - 见README.md 179 | 180 | # AUFS优点 181 | 182 | - 成熟度以及和Docker的融合性 183 | - Debian/Ubuntu 内核默认支持 184 | - mount()调用快,因此创建容器速度快 185 | - 启动n个容器,只会从磁盘加载一次 186 | 187 | # AUFS缺点 188 | 189 | - Read/write操作几乎无性能损失 190 | - open()有时候会很慢: 191 | - 1. 文件太大(log,数据库文件) 192 | - 2. 层级太深 193 | 194 | 195 | # BTRFS 196 | 197 | - Butter FS,Better FS? 198 | - B-tree file system,以大规模存储位目标 199 | - Oracle 2007 200 | - 受ZFS影响 201 | - 支持快照、CoW和回滚 202 | - CentOS 7.1可用,preview 203 | 204 | # BTRFS 205 | 206 | - 文件系统级别的CoW 207 | - 数据分为chunk,可存储meta和data 208 | - diff快 209 | - 基于subvolume + snapshot 210 | - 要求Docker运行于BTRFS之上(/var/lib/docker) 211 | - Docker相关代码好像只有几百行 212 | 213 | # overlay 214 | 215 | - 内核3.18 216 | - 类似AUFS,不过只有两个分支 217 | - 但是每个分支也可以是overlay的 218 | - 性能优于AUFS 219 | - 现在需要在ext4上运行 220 | 221 | # VFS 222 | 223 | - 没有CoW,每次拷贝 224 | - 不需要内核特性支持 225 | - 浪费空间 226 | - 慢 227 | - 适宜移植到其他平台 228 | 229 | # ZFS 230 | 231 | - Solaris(现Oracle) 232 | - 2005年发布 233 | - Zettabyte File System 234 | - 1 ZiB(泽字节) = 1,099,511,627,776 (1024的4次方)GiB 235 | - 也被移植到包括Linux在内的其他OS上 236 | 237 | # Device Mapper 238 | 239 | - RAID(dm-raid) 240 | - 设备加密(dm-crypt) 241 | - 快照(snapshots) 242 | - 延迟写入(dm-delay) 243 | - Docker未使用LVS 244 | - Docker : thin-provisioning + snapshot 245 | 246 | # thin provisioning 247 | 248 | - dm-thin/dm-thinp 249 | - 数据存放在两个文件,data和metadata 250 | - data 也叫做block pool(block:默认64KB,最大1G) 251 | - 从存储池(block池)分配逻辑设备 252 | - dm-thin将逻辑设备mount成容器的文件系统 253 | - 每次发生CoW(写入),才去分配block 254 | - metadata保存着快照中虚拟位移和pool中物理位移的对应关系 255 | 256 | ## thin provisioning 257 | 258 | - Docker镜像和容器都有自己的block设备 259 | - 默认data大小100GB(meta为2G) 260 | - 镜像大小10GB 261 | - 可以分配大于10个的容器 262 | - 如果一个block没有被写入,则不会真正分配物理磁盘 263 | - 可超卖 264 | 265 | # Device Mapper 266 | 267 | ![](./images/dm-block-mapping.png) 268 | 269 | 图片来源: http://www.school.ctc-g.co.jp/columns/nakai/nakai59.html 270 | 271 | # Device Mapper 272 | 273 | ![](./images/dm-snapshot.png) 274 | 275 | 图片来源: http://www.school.ctc-g.co.jp/columns/nakai/nakai59.html 276 | 277 | 278 | # Device Mapper 279 | 280 | ![](./images/dm-remap.png) 281 | 282 | 283 | # Device Mapper 284 | 285 | - 块级别而不是文件级别的CoW 286 | - 随时对镜像(->容器)或者容器(->镜像)做快照 287 | - 不依赖于文件系统(在FS之下) 288 | 289 | # Device Mapper相关命令 290 | 291 | - docker info 292 | - losetup 293 | - 设备名: docker-MAJ:MIN-INO 294 | - MAJ: block major 295 | - MIN: block minor 296 | - INO: inode number 297 | 298 | # 演示5 299 | 300 | - 见README.md 301 | 302 | 303 | # Device Mapper优点 304 | 305 | - 容器自己的block设备 306 | - 位于fs下层,支持多种文件系统类型 307 | - 可共享block 308 | 309 | # Device Mapper缺点 310 | 311 | - 不能直接查看layer之间的diff 312 | - docker diff慢 313 | - data和metadata基于sparse文件 314 | - loop device而不是真正的/dev设备 315 | - 每启动1次容器,都需要从磁盘加载一次 316 | - 崩溃报告较多 317 | 318 | # 结论 319 | 320 | - 类PaaS高密度 321 | - AUFS(或overlay) 322 | - 频繁写大文件? 323 | - Device Mapper或者BTRFS 324 | 325 | # 课后作业 326 | 327 | - docker pull 328 | - docker history|inspect 329 | - docker images/rmi 330 | - docker commit 331 | - docker push 332 | 333 | 334 | -------------------------------------------------------------------------------- /lesson-04/app/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM liubin/ruby:2.2.2 2 | 3 | 4 | MAINTAINER bin liu 5 | 6 | LABEL version="0.0.1" lang="myapp" 7 | 8 | COPY app.rb /app/app.rb 9 | 10 | WORKDIR /app 11 | 12 | RUN gem sources --remove https://rubygems.org/ \ 13 | && gem sources -a http://ruby.taobao.org/ 14 | 15 | RUN gem install sinatra 16 | 17 | EXPOSE 4567 18 | 19 | CMD ["ruby", "app.rb"] 20 | 21 | -------------------------------------------------------------------------------- /lesson-04/app/app.rb: -------------------------------------------------------------------------------- 1 | require 'sinatra' 2 | 3 | get '/' do 4 | 'Hello world!' 5 | end 6 | 7 | set :bind, '0.0.0.0' 8 | -------------------------------------------------------------------------------- /lesson-04/dockerfiles/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM centos:7 2 | 3 | MAINTAINER bin liu 4 | 5 | 6 | # 单独添加一个文件 7 | ADD files/file1.txt /dir1 8 | ADD files/file2.txt /dir2/ 9 | 10 | # 添加多个文件 11 | # Step 4 : ADD files/* /dir3 12 | # When using ADD with more than one source file, the destination must be a directory and end with a / 13 | # ADD files/* /dir3 14 | 15 | ADD files/* /dir4/ 16 | 17 | 18 | # src为文件夹 19 | ADD files /dir5 20 | ADD files /dir6/ 21 | ADD files/ /dir7/ 22 | 23 | # 添加URL文件(带文件名) 24 | ADD https://raw.githubusercontent.com/docker/docker/master/Dockerfile /url1 25 | 26 | ADD https://raw.githubusercontent.com/docker/docker/master/Dockerfile /url2/ 27 | 28 | 29 | # 添加URL文件(不带文件名) 30 | ADD https://github.com/ /url3 31 | 32 | # Step 8 : ADD https://github.com/ /url4/ 33 | # Downloading 17.63 kB 34 | # cannot determine filename from url: https://github.com/ 35 | 36 | # ADD https://github.com/ /url4/ 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /lesson-04/dockerfiles/Dockerfile-entrypoint-shell: -------------------------------------------------------------------------------- 1 | FROM centos:7 2 | 3 | MAINTAINER bin liu 4 | 5 | ENTRYPOINT top -b -------------------------------------------------------------------------------- /lesson-04/files/file1.txt: -------------------------------------------------------------------------------- 1 | a 2 | -------------------------------------------------------------------------------- /lesson-04/files/file2.txt: -------------------------------------------------------------------------------- 1 | b 2 | -------------------------------------------------------------------------------- /lesson-04/keynote.md: -------------------------------------------------------------------------------- 1 | # Docker入门与实践 2 | 3 | Lesson-04 使用Dockerfile构建镜像 4 | 刘斌@Alauda 5 | 2015年8月 6 | 7 | # 本节概要 8 | 9 | - 掌握构建镜像的方式 10 | - docker build命令 11 | - Dockerfile语法 12 | 13 | # 构建镜像的方式 14 | 15 | - docker commit 16 | - Dockerfile 17 | - Packer类 18 | 19 | # Dockerfile是什么 20 | 21 | - 构建镜像的说明书 22 | - DSL语法 23 | - docker inspect 24 | 25 | # 为什么用Dockerfile 26 | 27 | - 版本控制(追踪和回滚) 28 | - 公开透明 29 | - 一定程度的可重现 30 | 31 | # 使用Dockerfile构建的流程 32 | 33 | - 编写Dockerfile 34 | - 执行docker build命令 35 | 36 | # 演示 37 | 38 | - 构建Ruby镜像 39 | 40 | 41 | # docker build命令 42 | 43 | - docker build -t liubin/someimg[:sometag] path 44 | - path: 本地路径、远程URL和 "-" 45 | 46 | # 从STDIN接收压缩数据 47 | 48 | - docker build - < context.tar.gz 49 | - bzip2/gzip/xz 50 | 51 | # 构建环境(Build Context) 52 | 53 | - 包含Dockerfile的文件夹下的所有内容 54 | - ADD file 55 | 56 | # 构建环境支持git仓库 57 | 58 | - git clone --depth 1 --recursive 59 | - 还能指定git仓库的分支和目录 60 | - https://somegit.com/repo.git#fa3424fa:path1 61 | 62 | 63 | # Dockerfile指令格式 64 | 65 | - 不区分大小写,指令习惯大写 66 | - 按顺序读取 67 | - 以#开头的为注释 68 | 69 | # Dockerfile指令格式 70 | 71 | ```bash 72 | # Comment 73 | INSTRUCTION arguments 74 | ``` 75 | 76 | # ENV变量 77 | 78 | ```bash 79 | ENV foo /bar 80 | WORKDIR ${foo} # WORKDIR /bar 81 | ADD . $foo # ADD . /bar 82 | ``` 83 | 84 | # 可以使用ENV变量的指令 85 | 86 | - ADD/COPY 87 | - WORKDIR 88 | - EXPOSE 89 | - VOLUME 90 | 91 | # cache 92 | 93 | - 缓存加快速度 94 | - --no-cache 95 | 96 | # 也能限制build过程使用的资源 97 | 98 | - -m 99 | - -c 100 | 101 | # Tips: Dockerfile只能命名为Dockerfile? 102 | 103 | - docker build -f other-docker-file 104 | 105 | # .dockerignore 106 | 107 | - 等于 .gitignore 108 | - 指定不需要发送到daemon的文件(夹) 109 | 110 | # .dockerignore 111 | 112 | ```bash 113 | */temp* 114 | */*/temp* 115 | temp? 116 | *.md 117 | !LICENSE.md 118 | ``` 119 | 120 | 121 | # FROM指令 122 | 123 | - FROM 124 | - FROM : 125 | - FROM @ 126 | 127 | 128 | # MAINTAINER指令 129 | 130 | - MAINTAINER 131 | 132 | # RUN指令 133 | 134 | - RUN cmd arg (/bin/sh -c) 135 | - RUN ["cmd", "arg1", "arg2"] (exec格式) 136 | - RUN ["/bin/bash", "-c", "echo hello"] 137 | - exec格式需使用双引号而不是单引号 138 | 139 | # 状态修改 140 | 141 | - 下载、安装文件 142 | - 创建目录、文件 143 | - 拷贝、移动文件 144 | 145 | # 状态修改 146 | 147 | - cd 148 | - ls 149 | - pwd 150 | 151 | # 测试 152 | 153 | - RUN [ "echo", "$HOME" ] 154 | 155 | # 测试 156 | 157 | - RUN [ "sh", "-c", "echo", "$HOME" ] 158 | 159 | # 建议 160 | 161 | - 多条换行写 162 | - 避免单行的RUN apt-get update 163 | - 避免类似apt-get upgrade等命令 164 | 165 | # 建议 166 | 167 | ```bash 168 | RUN apt-get update && apt-get install -y \ 169 | package-bar \ 170 | package-baz \ 171 | package-foo 172 | ``` 173 | 174 | # LABEL 175 | 176 | - 镜像元数据 177 | - LABEL = = = ... 178 | - LABEL "com.example.vendor"="ACME Incorporated" 179 | - 继承父镜像标签 180 | - 建议一行写多个label,节省镜像层 181 | 182 | # ENTRYPOINT指令 183 | 184 | - ENTRYPOINT command param1 param2 (shell form) 185 | - ENTRYPOINT ["cmd", "param1", "param2"] (exec form) 186 | - docker run image some-command 187 | - 可通过docker run --entrypoint覆盖 188 | - 最后一条ENTRYPOINT指令有效 189 | 190 | # Shell形式 191 | 192 | - 忽略命令行参数和CMD指令 193 | 194 | # Exec形式 195 | 196 | - 不启动shell 197 | 198 | # CMD指令 199 | 200 | - 指定容器默认启动程序 201 | - CMD ["executable","param1","param2"] 202 | - CMD ["param1","param2"] 203 | - CMD command param1 param2 (shell form) 204 | - 只有最后一条CMD指令生效 205 | 206 | 207 | # Dockerfile 常用设计模式 208 | 209 | - 必须都用JSON数组格式 210 | 211 | # Dockerfile 常用设计模式 212 | 213 | ```bash 214 | ENTRYPOINT ["s3cmd"] 215 | CMD ["--help"] 216 | 217 | $ docker run s3cmd 218 | 219 | $ docker run s3cmd ls s3://mybucket 220 | ``` 221 | 222 | # EXPOSE 223 | 224 | - 仅是声明 225 | - 不会自动打开,-p或-P 226 | - EXPOSE [...] 227 | 228 | # ENV 229 | 230 | - ENV 231 | - ENV = ... 232 | - 继承性 233 | 234 | # ENV示例 235 | 236 | ```bash 237 | ENV myName="John Doe" myDog=Rex\ The\ Dog \ 238 | myCat=fluffy 239 | and 240 | 241 | ENV myName John Doe 242 | ENV myDog Rex The Dog 243 | ENV myCat fluffy 244 | ``` 245 | 246 | # 减少不必要的ENV 247 | 248 | - RUN = 249 | 250 | # ADD 251 | 252 | - 向镜像添加文件 253 | 254 | - ADD ... 255 | - ADD ["",... ""] 256 | - 文件、文件夹和URL 257 | 258 | # 259 | 260 | - 文件需要位于 build context下 261 | - src可包含通配符(filepath.Match) 262 | - src为URL,文件名可以从URL推导 263 | - src为文件夹,所有文件夹内容被拷贝 264 | - 为压缩(gzip/bzip2/xz)文件,将会被解开(tar -x) 265 | 266 | # 267 | 268 | ```bash 269 | ADD hom* /mydir/ 270 | ADD hom?.txt /mydir/ 271 | ``` 272 | 273 | # 274 | 275 | - 绝对路径 276 | - 相对于WORKDIR的路径 277 | - 新文件(夹)的UID=0,GID=0 278 | - 为URL则新文件属性为600 279 | - 如果指定了多个src,则dest必须以/结尾(否则出错) 280 | - 建议dest如果为文件夹,则在后面都加上/ 281 | 282 | # 283 | 284 | ```bash 285 | # adds "test" to `WORKDIR`/aDir/ 286 | ADD test aDir/ 287 | ``` 288 | 289 | 290 | # src为URL 291 | 292 | - ADD http://abc.com/somfile /file1 293 | - ADD http://abc.com/somfile /file2/(somefile) 294 | - ADD http://abc.com/ /file3 295 | - ADD http://abc.com/ /file4/ (出错) 296 | - 建议URL和dest都写明确,不要让Docker去推测 297 | 298 | 299 | # COPY指令 300 | 301 | - 和ADD一样 302 | - COPY ... 303 | - COPY ["",... ""] 304 | 305 | # ADD还是COPY? 306 | 307 | - 推荐COPY 308 | - 没有URL和自动解压 309 | - 减少不确定性 310 | 311 | - 不同类型的文件单独拷贝(最大效果利用缓存) 312 | - 手工下载文件后删除(减小镜像尺寸) 313 | 314 | - 尽量将全部操作都通过Dockerfile展现 315 | 316 | 317 | # VOLUME 318 | 319 | - VOLUME ["/data"] 320 | - VOLUME /var/log 321 | - VOLUME /var/log /var/db 322 | 323 | 324 | 325 | # VOLUME测试 326 | 327 | ```bash 328 | FROM ubuntu 329 | RUN mkdir /myvol 330 | RUN echo "hello world" > /myvol/greeting 331 | VOLUME /myvol 332 | ``` 333 | 334 | # USER 335 | 336 | - USER name or UID 337 | - 影响RUN/CMD/ENTRYPOINT 338 | - RUN groupadd -r postgres && useradd -r -g postgres postgres 339 | - UID/GID不能保证可重现性,可显示指定 340 | - 默认为root 341 | 342 | # USER 343 | 344 | ```bash 345 | USER user 346 | USER user:group 347 | USER uid 348 | USER uid:gid 349 | USER user:gid 350 | USER uid:group 351 | ``` 352 | 353 | # WORKDIR 354 | 355 | - WORKDIR /path/to/workdir 356 | - 影响后续RUN/CMD/ENTRYPOINT/COPY/ADD指令 357 | - 可多次使用 358 | 359 | 360 | # 小测试 361 | 362 | ```bash 363 | WORKDIR /a 364 | WORKDIR b 365 | WORKDIR c 366 | RUN pwd 367 | # pwd命令的结果? 368 | ``` 369 | 370 | # 小测试 371 | 372 | - 结果是: 373 | - /a/b/c 374 | 375 | 376 | # 小测试 377 | 378 | ```bash 379 | ENV DIRPATH /path 380 | WORKDIR $DIRPATH/$DIRNAME 381 | RUN pwd 382 | # pwd命令的结果? 383 | ``` 384 | 385 | # 小测试 386 | 387 | - 结果是: 388 | - /path/$DIRNAME 389 | - 只能替换Dockerfile设置的env环境变量 390 | 391 | # WORKDIR使用建议 392 | 393 | - 建议多使用绝对路径 394 | - 使用WORKDIR替换"cd .." 395 | 396 | # ONBUILD指令 397 | 398 | - ONBUILD [INSTRUCTION] 399 | - 子镜像构建触发器,不遗传,不能嵌套 400 | - 在FROM中执行 401 | - 不能通过ONBUILD执行FROM和MAINTAINER指令 402 | - 就像在衍生镜像的FROM指令后执行 403 | 404 | 405 | # 能通过docker run覆盖的镜像参数 406 | 407 | - Dockerfile的设置可覆盖 408 | - FROM/MAINTAINER/RUN/ADD 409 | - CMD/ENTRYPOINT/EXPOSE/ENV/VOLUME/USER/WORKDIR 410 | 411 | # CMD 412 | 413 | - docker run -it cnetos:7 bash 414 | 415 | # ENTRYPOINT 416 | 417 | - --entrypoint="" 418 | 419 | # EXPOSE 420 | 421 | - Dockerfile里唯一对网络设置选项 422 | - -P或-p 423 | - -p containerPort 424 | - -p hostPort:containerPort 425 | - -p ip:hostPort:containerPort 426 | - -p ip::containerPort 427 | 428 | 429 | # ENV 430 | 431 | - 预设: HOME/HOSTNAME/PATH/TERM 432 | - --link 433 | - -e "deep=purple" 434 | 435 | # VOLUME 436 | 437 | - -v=[] [host-dir:]container-dir[:rw|ro] 438 | - --volumes-from="" 439 | 440 | # USER 441 | 442 | - 默认为root 443 | - -u="": Username or UID 444 | 445 | # WORKDIR 446 | 447 | - -w="" 448 | 449 | 450 | # 最佳实践 451 | 452 | - 使用.dockerignore文件 453 | - 减少层数 454 | - 最小安装 455 | - 注意build cache(apt-get -y update问题) 456 | 457 | # 课后作业 458 | 459 | - 基于centos:7构建自己的语言栈 460 | - COPY 461 | - WORKDIR/ENV 462 | - EXEC/CMD 463 | -------------------------------------------------------------------------------- /lesson-04/ruby/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM centos:7 2 | 3 | MAINTAINER bin liu 4 | 5 | LABEL version="2.2.2" lang="ruby" 6 | 7 | ENV RUBY_MAJOR 2.2 8 | ENV RUBY_VERSION 2.2.2 9 | 10 | RUN yum install -y wget tar gcc g++ make automake autoconf curl-devel openssl-devel zlib-devel httpd-devel apr-devel apr-util-devel sqlite-devel 11 | 12 | RUN cd /tmp \ 13 | && wget http://cache.ruby-lang.org/pub/ruby/2.2/ruby-2.2.2.tar.gz \ 14 | && tar zxvf ruby-2.2.2.tar.gz \ 15 | && cd ruby-2.2.2 \ 16 | && autoconf \ 17 | && ./configure --disable-install-doc \ 18 | && make \ 19 | && make install \ 20 | && rm -rf /tmp/ruby-2.2.2* 21 | 22 | # skip installing gem documentation 23 | RUN echo -e 'install: --no-document\nupdate: --no-document' >> "$HOME/.gemrc" 24 | 25 | ENV GEM_HOME /usr/local/bundle 26 | ENV PATH $GEM_HOME/bin:$PATH 27 | 28 | ENV BUNDLER_VERSION 1.10.6 29 | 30 | RUN gem install bundler --version "$BUNDLER_VERSION" \ 31 | && bundle config --global path "$GEM_HOME" \ 32 | && bundle config --global bin "$GEM_HOME/bin" 33 | 34 | # don't create ".bundle" in all our apps 35 | ENV BUNDLE_APP_CONFIG $GEM_HOME 36 | 37 | CMD [ "irb" ] 38 | 39 | -------------------------------------------------------------------------------- /lesson-05/README.md: -------------------------------------------------------------------------------- 1 | # Lesson-05 构建私有镜像服务器 2 | 3 | # 使用Registry 4 | 5 | ## 启动Registry 6 | 7 | ``` 8 | $ sudo docker run -d -p 5000:5000 \ 9 | --restart=always --name registry registry:2 10 | ``` 11 | 12 | ## 使用Registry 13 | 14 | ``` 15 | # sudo docker run -it centos:7 bash 16 | [root@85198a3c97fc /]# vi /start.sh 17 | [root@85198a3c97fc /]# chmod +x /start.sh 18 | [root@85198a3c97fc /]# /start.sh 19 | from private registry 20 | [root@85198a3c97fc /]# cat /start.sh 21 | #!/bin/sh 22 | echo "from private registry" 23 | 24 | [root@85198a3c97fc /]# exit 25 | exit 26 | [root@docker101vm ~]# sudo docker commit 85198a3c97fc localhost:5000/testimg2 27 | 11b2d12f02fcd5564eeace11aaa03854da7a3427cf0a1168dc8c93fb83ba8b9d 28 | [root@docker101vm ~]# sudo docker images 29 | REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE 30 | localhost:5000/testimg2 latest 11b2d12f02fc 9 seconds ago 172.2 MB 31 | 32 | [root@docker101vm ~]# sudo docker push localhost:5000/testimg2 33 | The push refers to a repository [localhost:5000/testimg2] (len: 1) 34 | 11b2d12f02fc: Image already exists 35 | 7322fbe74aa5: Image successfully pushed 36 | c852f6d61e65: Image successfully pushed 37 | f1b10cd84249: Image already exists 38 | Digest: sha256:f991c80cb3ca59e6de3a3fa69c0217093bcbaacbafda7254bf237291b8e0f0f5 39 | [root@docker101vm ~]# sudo docker run localhost:5000/testimg2 /start.sh 40 | from private registry 41 | [root@docker101vm ~]# curl http://localhost:5000/v2/testimg2/tags/list 42 | {"name":"testimg2","tags":["latest"]} 43 | 44 | ``` 45 | 46 | 47 | # 认证 48 | 49 | ## Basic认证 50 | 51 | ### 创建证书 52 | 53 | ``` 54 | mkdir -p certs && openssl req \ 55 | -newkey rsa:4096 -nodes -sha256 -keyout certs/domain.key \ 56 | -x509 -days 365 -out certs/domain.crt 57 | 58 | Country Name (2 letter code) [XX]:CN 59 | State or Province Name (full name) []: 60 | Locality Name (eg, city) [Default City]:Beijing 61 | Organization Name (eg, company) [Default Company Ltd]: 62 | Organizational Unit Name (eg, section) []: 63 | Common Name (eg, your name or your server's hostname) []:private-registry.com 64 | Email Address []: 65 | 66 | ``` 67 | 68 | 69 | 将证书拷贝到系统目录 70 | 71 | ``` 72 | mkdir -p /etc/docker/certs.d/private-registry.com:6000/ 73 | 74 | cp certs/domain.crt /etc/docker/certs.d/private-registry.com:6000/ca.crt 75 | 76 | ``` 77 | 78 | 添加host记录 79 | 80 | ``` 81 | vi /etc/hosts 82 | 83 | 128.199.218.41 private-registry.com 84 | 85 | ``` 86 | 87 | ### 创建用户和密码 88 | 89 | ``` 90 | docker run --entrypoint htpasswd registry:2 -Bbn liubin 12345678 > auth/htpasswd 91 | ``` 92 | 93 | ### 启动Registry 94 | 95 | ``` 96 | docker run -d -p 6000:5000 --restart=always --name registry \ 97 | -v `pwd`/auth:/auth \ 98 | -e "REGISTRY_AUTH=htpasswd" \ 99 | -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \ 100 | -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \ 101 | -v `pwd`/certs:/certs \ 102 | -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \ 103 | -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \ 104 | registry:2 105 | ``` 106 | 107 | ### login 并 push镜像 108 | 109 | ``` 110 | docker login private-registry.com:6000 111 | 112 | docker tag busybox private-registry.com:6000/basic-auth-img 113 | 114 | docker push private-registry.com:6000/basic-auth-img 115 | 116 | docker stop registry 117 | 118 | docker rm -v registry 119 | ``` 120 | 121 | ## Token认证 122 | 123 | 124 | ### Portus项目 125 | 126 | 使用了 [Portus](http://suse.github.io/Portus/) 项目。 127 | 128 | ``` 129 | cd 130 | 131 | git clone https://github.com/liubin/Portus.git 132 | 133 | cd Portus 134 | ``` 135 | 136 | 修改Docker守护进程参数 137 | 138 | ``` 139 | vi /lib/systemd/system/docker.service 140 | 141 | ExecStart=/usr/bin/docker daemon --insecure-registry private-registry.com:5000 -H fd:// 142 | ``` 143 | 144 | 启动 145 | 146 | ``` 147 | ./compose-setup.sh 148 | 149 | ``` 150 | 151 | ### 注册用户 152 | 153 | 154 | 打开浏览器,注册用户,添加registry 155 | 156 | - Name: private-registry.com 157 | - Hostname: private-registry.com:5000(千万别忘记写端口号) 158 | 159 | 添加host记录(在主机上,如果用了Vagrant,需要在主机和Vagrant中进行) 160 | 161 | ``` 162 | 127.0.0.1 private-registry.com 163 | ``` 164 | 165 | 166 | ### 在命令行login 167 | 168 | ``` 169 | docker login -u liubin -p 12345678 -e liubin0329@gamil.com private-registry.com:5000 170 | 171 | docker tag busybox private-registry.com:5000/liubin/busybox 172 | 173 | docker push private-registry.com:5000/liubin/busybox 174 | 175 | docker tag busybox private-registry.com:5000/busybox:tag1 176 | 177 | docker push private-registry.com:5000/busybox:tag1 178 | 179 | 180 | ``` 181 | 182 | # 参考 183 | 184 | * 项目地址 185 | 186 | https://github.com/docker/distribution 187 | 188 | * Registry API 189 | 190 | https://docs.docker.com/registry/spec/api/ 191 | 192 | * 认证 193 | 194 | - https://docs.docker.com/registry/authentication/ 195 | - https://github.com/docker/distribution/blob/master/docs/deploying.md 196 | 197 | # 视频地址 198 | 199 | * [构建私有镜像服务器](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2731) 200 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker12.jpg) 201 | * [为私有镜像服务添加Basic认证...](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2732) 202 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker13.jpg) 203 | * [为私有镜像服务添加Token认证...](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2733) 204 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker14.jpg) 205 | -------------------------------------------------------------------------------- /lesson-05/auth/domain.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFizCCA3OgAwIBAgIJANxRQ7S8qVmEMA0GCSqGSIb3DQEBCwUAMFwxCzAJBgNV 3 | BAYTAkNOMRAwDgYDVQQHDAdCZWlqaW5nMRwwGgYDVQQKDBNEZWZhdWx0IENvbXBh 4 | bnkgTHRkMR0wGwYDVQQDDBRwcml2YXRlLXJlZ2lzdHJ5LmNvbTAeFw0xNTA4MDkw 5 | NTQ4MTVaFw0xNjA4MDgwNTQ4MTVaMFwxCzAJBgNVBAYTAkNOMRAwDgYDVQQHDAdC 6 | ZWlqaW5nMRwwGgYDVQQKDBNEZWZhdWx0IENvbXBhbnkgTHRkMR0wGwYDVQQDDBRw 7 | cml2YXRlLXJlZ2lzdHJ5LmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC 8 | ggIBAMAbN0bWP+UARipgLCVtddOzZl6i00mKnQoW2BD9VhkyvWW2Kqz0zN305IE8 9 | JYoQv8ZI2WJULAfJ7PXqsxAATx7n9K2QBodjtP8xJPPHOEEKW9pg+Nux9Xefz48P 10 | w/oBURoV4dyRhaz86ySbqbEdaPPUojti8vsNfCpbEawGWgUdVE5fKKQwLaS7dD15 11 | spC/aB00u61imjuafvEYR2RwMSVVleFF9iS6Jn1MBRaX3l8Q5/knXMAL001aV9tS 12 | Pjd7uK2j1ZJvln2kgneks19fZWWcZ9ASDWsieQ6IlVmYYDUc/kbrZZp2VMri/ntT 13 | fgeiRGB6lBmhNUPIE2PPUSrK2SX/NmbUfRljnhpJ8qiB1fJIjmpXIoLcbY/+meN/ 14 | Tj2sCK4RPa30NNXoK7kmJ93uZQATyiIp+iWbWiztQm5GZhI4s0WPszg71XkHyyRA 15 | bepFcZNix8ghEJ9OqVqj57fyicAeFY3jiUbRpuo9PiHdFFq8w5teSl4rrb5nQSM1 16 | BxIFAziUN0xD5jCDWAS8nJ/D3wnqz/d62grAmem7rZLf4z4A1QIFOa9JqFVWUlrn 17 | yoi3MXpXy6KkGY/xgufS4eRMmOcgkr30w49U2M1ONQEhC847kq/4y/C+b52mUHh+ 18 | NjvlWbRG9z2YABLUPJGjK/6d7wFxedNDX/YsWVqxH57rjGTlAgMBAAGjUDBOMB0G 19 | A1UdDgQWBBSLZzdcQtcFPgA7Iml3ZUYv91CjzzAfBgNVHSMEGDAWgBSLZzdcQtcF 20 | PgA7Iml3ZUYv91CjzzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4ICAQAh 21 | gSWxbsW4wbbAKeKH7bokK2tH6wMjN2XIjd5mibYFnuVu4O1zN8mY45kxITsr4GTi 22 | Zhud6Vdj95ZNYEe/tFSkKD4Zcg7AoMw8hDPxsmI2lkd3+D4GzbAJI57Fmet5tCik 23 | ashBQIsnYEVHCNuSyljyUwuslvn8zNLJSSCp+LiZVShCNJ4O7nS+nwxD4Kez95xO 24 | 7iZ+/KLKtWRpNokMQU6sFdqNmmHKf1X3oWal8yIfZ/DnGSnOyRuDA6Se3NpVQKZy 25 | 7eyWQeVX3zouTHF5vmMVGJ3vniIXZgmDZY5B+fQgO1WEdIvqP0iFt+BCMDgECPO4 26 | XL02vYtaCC/AaWt3upgMCCk8P6rl5PblUUFR7uZVC+zmTrZfXVV4luyJ39siqZdR 27 | WS5+rg8bi42l4fxNbTAS23aNFw1cS2wqwiwYV7W6+EFNXl6dDm2pZ334sZZFZIHC 28 | GlvycsVtuggjocuOluccEWPLIyvGjSYghGjcKsLcbNeCNy/yL6rXcu1rydjQPa7T 29 | b4oAsTLODDWFOKArTh9/eQWgWxoa8sZ+86V+ErYKEfX9Wv3bO+AwfyUUXy1+a/8B 30 | KXul1RXz91dinQqEUXxCbfoxUdmNr5sWbm/uFlNrCqVi/NrJenmxVQezQhXABfIS 31 | oFs7VISoJeRHzqUxmfq/l2fVS5/Q33fF8ujNm/tExQ== 32 | -----END CERTIFICATE----- 33 | -------------------------------------------------------------------------------- /lesson-05/auth/domain.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | 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 51 | miaEM+UDsXXhkccPXCLPgJPHFKOHNRYN 52 | -----END PRIVATE KEY----- 53 | -------------------------------------------------------------------------------- /lesson-05/auth/htpasswd: -------------------------------------------------------------------------------- 1 | testuser:$2y$05$YheaMXycRTDWOckjFx7PlePYSh/gV2hCCZ12E2dFTLb2KJ42LAqoW 2 | 3 | -------------------------------------------------------------------------------- /lesson-05/auth/registry.conf: -------------------------------------------------------------------------------- 1 | upstream docker-registry { 2 | server registry:5000; 3 | } 4 | 5 | server { 6 | listen 443 ssl; 7 | server_name private-registry.com; 8 | 9 | # SSL 10 | ssl_certificate /etc/nginx/conf.d/domain.crt; 11 | ssl_certificate_key /etc/nginx/conf.d/domain.key; 12 | 13 | # disable any limits to avoid HTTP 413 for large image uploads 14 | client_max_body_size 0; 15 | 16 | # required to avoid HTTP 411: see Issue #1486 (https://github.com/docker/docker/issues/1486) 17 | chunked_transfer_encoding on; 18 | 19 | location /v2/ { 20 | # Do not allow connections from docker 1.5 and earlier 21 | # docker pre-1.6.0 did not properly set the user agent on ping, catch "Go *" user agents 22 | if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))|Go ).*$" ) { 23 | return 404; 24 | } 25 | 26 | # To add basic authentication to v2 use auth_basic setting plus add_header 27 | auth_basic "registry.localhost"; 28 | auth_basic_user_file /etc/nginx/conf.d/registry.password; 29 | add_header 'Docker-Distribution-Api-Version' 'registry/2.0' always; 30 | 31 | proxy_pass http://docker-registry; 32 | proxy_set_header Host $http_host; # required for docker client's sake 33 | proxy_set_header X-Real-IP $remote_addr; # pass on real client's IP 34 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 35 | proxy_set_header X-Forwarded-Proto $scheme; 36 | proxy_read_timeout 900; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /lesson-05/auth/registry.password: -------------------------------------------------------------------------------- 1 | testuser:$apr1$SCscCYJd$5zvIZuj9mTOlMyhNlnDNl0 2 | -------------------------------------------------------------------------------- /lesson-05/certs/domain.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFizCCA3OgAwIBAgIJANxRQ7S8qVmEMA0GCSqGSIb3DQEBCwUAMFwxCzAJBgNV 3 | BAYTAkNOMRAwDgYDVQQHDAdCZWlqaW5nMRwwGgYDVQQKDBNEZWZhdWx0IENvbXBh 4 | bnkgTHRkMR0wGwYDVQQDDBRwcml2YXRlLXJlZ2lzdHJ5LmNvbTAeFw0xNTA4MDkw 5 | NTQ4MTVaFw0xNjA4MDgwNTQ4MTVaMFwxCzAJBgNVBAYTAkNOMRAwDgYDVQQHDAdC 6 | ZWlqaW5nMRwwGgYDVQQKDBNEZWZhdWx0IENvbXBhbnkgTHRkMR0wGwYDVQQDDBRw 7 | cml2YXRlLXJlZ2lzdHJ5LmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC 8 | ggIBAMAbN0bWP+UARipgLCVtddOzZl6i00mKnQoW2BD9VhkyvWW2Kqz0zN305IE8 9 | JYoQv8ZI2WJULAfJ7PXqsxAATx7n9K2QBodjtP8xJPPHOEEKW9pg+Nux9Xefz48P 10 | w/oBURoV4dyRhaz86ySbqbEdaPPUojti8vsNfCpbEawGWgUdVE5fKKQwLaS7dD15 11 | spC/aB00u61imjuafvEYR2RwMSVVleFF9iS6Jn1MBRaX3l8Q5/knXMAL001aV9tS 12 | Pjd7uK2j1ZJvln2kgneks19fZWWcZ9ASDWsieQ6IlVmYYDUc/kbrZZp2VMri/ntT 13 | fgeiRGB6lBmhNUPIE2PPUSrK2SX/NmbUfRljnhpJ8qiB1fJIjmpXIoLcbY/+meN/ 14 | Tj2sCK4RPa30NNXoK7kmJ93uZQATyiIp+iWbWiztQm5GZhI4s0WPszg71XkHyyRA 15 | bepFcZNix8ghEJ9OqVqj57fyicAeFY3jiUbRpuo9PiHdFFq8w5teSl4rrb5nQSM1 16 | BxIFAziUN0xD5jCDWAS8nJ/D3wnqz/d62grAmem7rZLf4z4A1QIFOa9JqFVWUlrn 17 | yoi3MXpXy6KkGY/xgufS4eRMmOcgkr30w49U2M1ONQEhC847kq/4y/C+b52mUHh+ 18 | NjvlWbRG9z2YABLUPJGjK/6d7wFxedNDX/YsWVqxH57rjGTlAgMBAAGjUDBOMB0G 19 | A1UdDgQWBBSLZzdcQtcFPgA7Iml3ZUYv91CjzzAfBgNVHSMEGDAWgBSLZzdcQtcF 20 | PgA7Iml3ZUYv91CjzzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4ICAQAh 21 | gSWxbsW4wbbAKeKH7bokK2tH6wMjN2XIjd5mibYFnuVu4O1zN8mY45kxITsr4GTi 22 | Zhud6Vdj95ZNYEe/tFSkKD4Zcg7AoMw8hDPxsmI2lkd3+D4GzbAJI57Fmet5tCik 23 | ashBQIsnYEVHCNuSyljyUwuslvn8zNLJSSCp+LiZVShCNJ4O7nS+nwxD4Kez95xO 24 | 7iZ+/KLKtWRpNokMQU6sFdqNmmHKf1X3oWal8yIfZ/DnGSnOyRuDA6Se3NpVQKZy 25 | 7eyWQeVX3zouTHF5vmMVGJ3vniIXZgmDZY5B+fQgO1WEdIvqP0iFt+BCMDgECPO4 26 | XL02vYtaCC/AaWt3upgMCCk8P6rl5PblUUFR7uZVC+zmTrZfXVV4luyJ39siqZdR 27 | WS5+rg8bi42l4fxNbTAS23aNFw1cS2wqwiwYV7W6+EFNXl6dDm2pZ334sZZFZIHC 28 | GlvycsVtuggjocuOluccEWPLIyvGjSYghGjcKsLcbNeCNy/yL6rXcu1rydjQPa7T 29 | b4oAsTLODDWFOKArTh9/eQWgWxoa8sZ+86V+ErYKEfX9Wv3bO+AwfyUUXy1+a/8B 30 | KXul1RXz91dinQqEUXxCbfoxUdmNr5sWbm/uFlNrCqVi/NrJenmxVQezQhXABfIS 31 | oFs7VISoJeRHzqUxmfq/l2fVS5/Q33fF8ujNm/tExQ== 32 | -----END CERTIFICATE----- 33 | -------------------------------------------------------------------------------- /lesson-05/certs/domain.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | 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 51 | miaEM+UDsXXhkccPXCLPgJPHFKOHNRYN 52 | -----END PRIVATE KEY----- 53 | -------------------------------------------------------------------------------- /lesson-05/docker-compose.yml: -------------------------------------------------------------------------------- 1 | registry: 2 | restart: always 3 | image: registry:2 4 | ports: 5 | - 6000:5000 6 | environment: 7 | REGISTRY_HTTP_TLS_CERTIFICATE: /certs/domain.crt 8 | REGISTRY_HTTP_TLS_KEY: /certs/domain.key 9 | REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /var/lib/registry 10 | REGISTRY_AUTH: htpasswd 11 | REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd 12 | REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm 13 | volumes: 14 | - /vagrant/lesson-05/data:/var/lib/registry 15 | - /vagrant/lesson-05/certs:/certs 16 | - /vagrant/lesson-05/auth:/auth -------------------------------------------------------------------------------- /lesson-05/images/index-and-registry.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-05/images/index-and-registry.png -------------------------------------------------------------------------------- /lesson-05/keynote.md: -------------------------------------------------------------------------------- 1 | # Docker入门与实践 2 | 3 | Lesson-05 构建私有镜像服务器 4 | 刘斌@Alauda 5 | 2015年8月 6 | 7 | # 本节概要 8 | 9 | - 什么是Registry和Index 10 | - 部署私有Registry 11 | - 集成Portus进行用户认证 12 | 13 | # 什么是Registry和Index 14 | 15 | - 保存镜像层以及meta信息 16 | - 用户认证,UI等Web接口 17 | 18 | # Registry 19 | 20 | - 存储镜像 21 | - 控制自己的部署pipeline 22 | - 23 | integrate image storage and distribution tightly into your in-house development workflow 24 | 25 | # Docker Distribution 26 | 27 | - 打包、传输、存储、交付内容的工具集 28 | - 以Registyry 2.0为主要产品 29 | - 还包括docs.docker.com的所有文档 30 | 31 | # Use cases 32 | 33 | - CI/CD 34 | - 大规模部署 35 | - 异地部署 36 | 37 | # 安装 38 | 39 | - Docker style 40 | - docker run -d -p 5000:5000 registry:2 41 | - 简单的难以置信 42 | - 软件交付方式 43 | - no wget && tar && pip install 44 | 45 | # 使用私有Registry 46 | 47 | - docker tag 48 | - docker push/pull 49 | 50 | # 使用私有Registry 51 | 52 | ```bash 53 | # docker tag centos:7 myregistry.com:5000/centos:7 54 | # docker push myregistry.com:5000/centos:7 55 | ``` 56 | 57 | # 查看Registry内部 58 | 59 | ```bash 60 | $ sudo docker exec -it registry bash 61 | cd /tmp 62 | ``` 63 | 64 | # 演示 65 | 66 | - 启动Registry 67 | - 向Registry push镜像 68 | 69 | 70 | # Storage Driver 71 | 72 | - 存储本身交给Storage Driver 73 | - 默认为本地文件系统,适合开发或者小规模 74 | - 也可以使用云存储,如S3、Azure和Ceph等,以及阿里云OSS 75 | - 甚至通过实现Storage API自定义storage backend 76 | 77 | 78 | # 将数据保存到Volume 79 | 80 | - -e REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/var/lib/registry 81 | - -v /myregistrydata:/var/lib/registry 82 | 83 | 84 | # 数据存储到Volume 85 | 86 | ```bash 87 | $ docker run -d -p 5000:5000 \ 88 | -e REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/var/lib/registry \ 89 | -v /myregistrydata:/var/lib/registry \ 90 | --restart=always --name registry registry:2 91 | ``` 92 | 93 | # Notification机制 94 | 95 | - webhooks/notification 96 | - log和report 97 | - email/bugsnap/newrelic 98 | 99 | # 安全对策 100 | 101 | - 支持TLS 102 | - 通过Nginx等进行basic authentication 103 | - 官方文档也有其他方式的认证和授权实现说明 104 | 105 | # 在公共网络上使用 106 | 107 | - 非localhost 108 | - 买一个证书(推荐) 109 | - 配置--insecure-registry 110 | - 自签名证书 111 | - 防火墙 112 | 113 | # 认证(Authentication) 114 | 115 | - docker login 116 | 117 | ![](images/index-and-registry.png) 118 | 119 | # 认证 120 | 121 | - Basic(Proxy)认证 122 | - Token 认证(delegated authentication) 123 | 124 | # Basic(Proxy)认证 125 | 126 | - 简单 127 | - 准备证书 128 | - 创建用户密码 129 | 130 | # Token认证 131 | 132 | - 需要实现 133 | - 复杂、大型组织 134 | 135 | # Portus 136 | 137 | - 开源:MariaDB + Rails + Registry 138 | 139 | # 课后作业 140 | 141 | - 运行自己的私有Registry 142 | - 构建一个镜像并push到该Registry 143 | - 在本地删除该镜像 144 | - 从私有镜像pull出来 145 | -------------------------------------------------------------------------------- /lesson-06/keynote.md: -------------------------------------------------------------------------------- 1 | # Docker入门与实践 2 | 3 | Lesson-06 Docker Hub和自动构建 4 | 刘斌@Alauda 5 | 2015年8月 6 | 7 | # 本节概要 8 | 9 | - Docker Hub功能简介 10 | - 在Docker Hub托管镜像 11 | - 自动构建 12 | 13 | # Docker Hub 14 | 15 | - 分发组件 16 | - 镜像托管 17 | - 系统办公 18 | - 免费和付费 19 | - 工作流 20 | 21 | # 主要功能 22 | 23 | - 镜像仓库 24 | - 自动构建(Automated Builds) 25 | - Webhooks 26 | - 组织(Organizations) 27 | - GitHub/Bitbucket集成 28 | 29 | # 官方镜像仓库 30 | 31 | - Official Repositories 32 | - docker-library/official-images 33 | - docker-library/docs 34 | 35 | # 官方镜像仓库标准 36 | 37 | - 基础OS镜像 38 | - 唾手可得的语言环境、软件 39 | - Dockerfile规范良好、文档详尽 40 | - 及时更新 41 | - 软件交付渠道 42 | 43 | # 和Docker Hub相关的命令 44 | 45 | - login/logout 46 | - pull/push 47 | - search 48 | 49 | # 自动构建 50 | 51 | - GitHub/BitBucket 52 | 53 | 54 | # 认证功能 55 | 56 | - ~/.docker/config.json 57 | 58 | # 自动构建过程 59 | 60 | - 添加commit hook 61 | - push后克隆到本地 62 | - 在本地build 63 | - 构建成功push镜像 64 | 65 | # 自动构建优势 66 | 67 | - 可信、可靠,保持最新 68 | - 支持GitHub/Bitbucket公开或私有仓库 69 | - 不能手工push镜像 70 | - 一个仓库对应多个自动构建 71 | - README.md即镜像说明 72 | 73 | 74 | # Repository links 75 | 76 | - 连接两个自动构建 77 | - 一个仓库有变化,则自动触发另一个仓库的自动构建 78 | - 不要循环连接 79 | 80 | 81 | # 远程构建触发器 82 | 83 | - Remote Build triggers 84 | - 通过POST发送构建请求 85 | - 5分钟只能请求1次 86 | - 上次构建未完成请求则被忽略 87 | - 指定镜像tag或Git的tag、分支等进行 88 | 89 | # Webhooks 90 | 91 | - HTTP call-back 92 | - 镜像更新时通知用户 93 | - Webhook chains 94 | 95 | # Webhook chains 96 | 97 | - 逐条执行 98 | - 前一hook验证(validate)之后,后一条才会执行 99 | - hook链只有全部hook都完成验证,才认为是完成。 100 | - 通过hook消息体中的callback_url进行POST验证 101 | - 验证消息内容 102 | - state:必选参数success/failure/error 103 | - description:显示在Docker Hub的详细信息,255字符 104 | - context:操作场景信息,100字符以内 105 | - target_url:用来查看hook执行结果的网址 106 | 107 | # 组织(团队) 108 | 109 | - Organizations and teams 110 | - Owners team具有创建team、仓库和自动构建的权限 111 | - 协作者 Collaborators 112 | - 读取私有仓库 113 | - 向非自动构建仓库push 114 | - Admin权限,修改仓库的描述,写作者;公开、私有以及删除仓库 115 | 116 | # 课后作业 117 | 118 | - 注册GitHub/Bitbucket和Docker Hub 119 | - 创建自动构建 120 | - 提交Dockerfile进行自动构建 121 | - 本地docker pull下载该自动构建镜像 122 | -------------------------------------------------------------------------------- /lesson-07/images/etcd-ambassador-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-07/images/etcd-ambassador-flow.png -------------------------------------------------------------------------------- /lesson-07/keynote.md: -------------------------------------------------------------------------------- 1 | # Docker入门与实践 2 | 3 | Lesson-07 Docker Link 4 | 刘斌@Alauda 5 | 2015年8月 6 | 7 | # 本节概要 8 | 9 | - 什么是Docker Linxk 10 | - Docker Link的功能 11 | - Docker Link的用法 12 | 13 | # 为什么需要Docker Link 14 | 15 | - 如何连接到Docker容器? 16 | - docker inspect 17 | - docker port 18 | 19 | # 命名的重要性 20 | 21 | - happy_newton 22 | - 容易理解 23 | 24 | - --name选项 25 | - 唯一 26 | 27 | # Docker Link的好处 28 | 29 | - 方便引用 30 | - 类似白名单 31 | - 安全:只有引用者才能访问端口 32 | 33 | # 第一个Docker Link 34 | 35 | ```bash 36 | docker run -d --name db training/postgres 37 | docker run -d -P --name web --link db:db training/webapp python app.py 38 | docker inspect -f "{{ .HostConfig.Links }}" web 39 | 40 | ``` 41 | 42 | # 目的容器如何认识源容器? 43 | 44 | - 环境变量 45 | - /etc/hosts文件 46 | 47 | # 环境变量来自哪里? 48 | 49 | - Dockerfile 50 | - docker run -e|-env-file 选项 51 | 52 | # Docker Link添加的环境变量 53 | 54 | - 根据--link参数别名创建 55 | - 来自源容器(此处有安全隐患) 56 | 57 | # Docker Link添加的环境变量 58 | 59 | - _NAME 60 | - // 61 | 62 | # 和端口相关的环境变量 63 | 64 | - _PORT: WEBDB_PORT=tcp://172.17.0.82:8080 65 | - prefix: _PORT__ 66 | - prefix_ADDR: WEBDB_PORT_8080_TCP_ADDR = 172.17.0.82 67 | - prefix_PORT: WEBDB_PORT_8080_TCP_PORT = 8080 68 | - prefix_PROTO: WEBDB_PORT_8080_TCP_PROTO = tcp 69 | - 环境变量数量 = n(port num) * 3 70 | 71 | # 源容器的其他环境变量 72 | 73 | - 全部 74 | - _ENV_ 75 | 76 | # 更新/etc/hosts 77 | 78 | - 在目标容器的/etc/hosts中,增加源容器条目 79 | 80 | # 更新/etc/hosts 81 | 82 | ```bash 83 | $ docker run -t -i --rm --link db:webdb training/webapp /bin/bash 84 | root@aed84ee21bde:/opt/webapp# cat /etc/hosts 85 | 172.17.0.7 aed84ee21bde 86 | . . . 87 | 172.17.0.5 webdb 6e5cdeb2d300 db 88 | 89 | ``` 90 | 91 | # /etc/hosts自动更新 92 | 93 | - 源容器重启后,会自动更新/etc/hosts条目 94 | - 环境变量不会更新 95 | - 建议使用/etc/hosts 96 | 97 | # 大使(ambassador)模式 98 | 99 | - 从 (consumer) --> (redis) 100 | - 到 (consumer) --> (redis-ambassador) --> (redis) 101 | - 或 (consumer) --> (redis-ambassador) ---network---> (redis-ambassador) --> (redis) 102 | - 解决跨主机通信 103 | 104 | 105 | # svendowideit/ambassador容器 106 | 107 | - socat 108 | - Docker Hub不活跃 109 | 110 | # 基于etcd的大使模式 111 | 112 | ![](images/etcd-ambassador-flow.png) 113 | 114 | 图片来源:https://coreos.com/assets/images/media/etcd-ambassador-flow.png 115 | 116 | 117 | # 课后作业 118 | 119 | - 在两个容器中使用link 120 | - 在目的容器中检查ENV,/etc/hosts等 121 | - 确认网络连通性 122 | 123 | -------------------------------------------------------------------------------- /lesson-08/keynote.md: -------------------------------------------------------------------------------- 1 | # Docker入门与实践 2 | 3 | Lesson-08 Docker Volume 4 | 刘斌@Alauda 5 | 2015年8月 6 | 7 | # 本节概要 8 | 9 | - Docker Volume简介 10 | - 使用数据卷进行数据管理 11 | - 数据卷的备份和恢复 12 | 13 | # 容器的数据去哪里了? 14 | 15 | - 随着容器消失了。。。 16 | - 容器启动不了了,如何备份出来? 17 | - 如何共享数据? 18 | - 等等问题 19 | 20 | # 容器种类 21 | 22 | - 有状态(stateful) 23 | - 无状态(stateless) 24 | 25 | # 数据卷 26 | 27 | - 透过Union FS 28 | - 持久化(persistent) 29 | - 共享(share) 30 | 31 | # 数据卷的用途、特点 32 | 33 | - 拷贝base镜像中的数据到卷 34 | - 在容器中共享和重用 35 | - 绕过Union FS(CoW) 36 | - 不会影响容器和镜像 37 | - 和容器的生命周期无关 38 | 39 | # 创建数据卷的方式 40 | 41 | - docker run -v 42 | - Dockerfile VOLUME 指令 43 | - 默认在 /var/lib/docker 下 44 | 45 | # 加载host文件夹为卷 46 | 47 | - -v /src/webapp:/opt/webapp 48 | - Windows 和 OS X 要 加上 Users前缀 49 | - 不可在Dockerfile中使用 50 | 51 | # 实验 52 | 53 | - /host:/container 54 | - /host存在文件 55 | - /container存在文件 56 | - 两者都存在文件 57 | 58 | 59 | # 指定映射权限 60 | 61 | ```bash 62 | /src/webapp:/opt/webapp:ro 63 | ``` 64 | 65 | # 也能mount单独文件 66 | 67 | ```bash 68 | docker run -v ~/.bash_history:/.bash_history 69 | ``` 70 | 71 | # 数据卷容器 72 | 73 | - data volume container 74 | - 在容器间共享数据 75 | 76 | # 创建数据卷容器 77 | 78 | ```bash 79 | $ docker create -v /dbdata --name dbdata training/postgres /bin/true 80 | $ docker run -d --volumes-from dbdata --name db1 training/postgres 81 | $ docker run -d --volumes-from dbdata --name db2 training/postgres 82 | $ docker run -d --name db3 --volumes-from db1 training/postgres 83 | ``` 84 | 85 | 86 | # Dangling数据卷 87 | 88 | - 幽灵卷 89 | - docker rm -v 90 | 91 | # 数据备份、恢复和迁移 92 | 93 | ```bash 94 | $ docker run --volumes-from dbdata -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata 95 | ``` 96 | 97 | # 课后作业 98 | 99 | - 通过-v启动第一个容器 100 | - 在该容器中对volume中的数据进行修改 101 | - 启动第二个容器,使用--volumes-from 102 | - 在第二个容器中查看volume中的数据 103 | 104 | -------------------------------------------------------------------------------- /lesson-09/example-1/Dockerfile: -------------------------------------------------------------------------------- 1 | # Docker101 course, Lesson-9 2 | FROM python:2.7 3 | ADD . /code 4 | WORKDIR /code 5 | RUN pip install -r requirements.txt 6 | CMD python app.py -------------------------------------------------------------------------------- /lesson-09/example-1/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | from redis import Redis 3 | import os 4 | app = Flask(__name__) 5 | redis = Redis(host='redis', port=6379) 6 | 7 | @app.route('/') 8 | def hello(): 9 | redis.incr('hits') 10 | return 'Hello World! I have been seen %s times.\n' % redis.get('hits') 11 | 12 | if __name__ == "__main__": 13 | app.run(host="0.0.0.0", debug=True) -------------------------------------------------------------------------------- /lesson-09/example-1/docker-compose.yml: -------------------------------------------------------------------------------- 1 | web: 2 | build: . 3 | command: python app.py 4 | ports: 5 | - "5000:5000" 6 | volumes: 7 | - .:/code 8 | links: 9 | - redis 10 | 11 | redis: 12 | image: redis -------------------------------------------------------------------------------- /lesson-09/example-1/requirements.txt: -------------------------------------------------------------------------------- 1 | flask 2 | redis -------------------------------------------------------------------------------- /lesson-09/example-2/docker-compose.yml: -------------------------------------------------------------------------------- 1 | web: 2 | image: wordpress 3 | links: 4 | - db:mysql 5 | ports: 6 | - 8080:80 7 | 8 | db: 9 | image: mariadb 10 | environment: 11 | MYSQL_ROOT_PASSWORD: rootASDF 12 | 13 | -------------------------------------------------------------------------------- /lesson-09/keynote.md: -------------------------------------------------------------------------------- 1 | # Docker入门与实践 2 | 3 | Lesson-09 Docker Compose 4 | 刘斌@Alauda 5 | 2015年8月 6 | 7 | # 本节概要 8 | 9 | - 什么是Docker Compose 10 | - 使用Docker Compose构建多容器应用 11 | - Docker Compose用法详解 12 | 13 | # 什么是Docker Compose 14 | 15 | - 定义和管理多Docker容器应用的工具 16 | - 非常适合在开发、预演和CI环境下使用 17 | - 目前不建议在生产环境 18 | 19 | # Compose涵盖功能 20 | 21 | - 定义、运行多容器应用 22 | - 一个文件定义 23 | - 一条命令启动 24 | - 一条命了几乎能干任何事情,从启动到销毁 25 | 26 | # 三步使用Compose 27 | 28 | - 通过Dockerfile定义应用镜像 29 | - 通过docker-compose.yml定义服务,容器在一个统一的隔离环境 30 | - docker-compose up 31 | 32 | # Compose管理整个应用的生命周期 33 | 34 | - 构建镜像,启动停止服务 35 | - 管理服务 36 | - 管理日志 37 | - 执行单条命令 38 | 39 | # 启动第一个例子 40 | 41 | ```bash 42 | $ docker-compose up -d 43 | $ docker-compose run web env 44 | $ docker-compose stop 45 | ``` 46 | 47 | # Compose命令说明 48 | 49 | - build:构建或者重新构建服务 50 | - kill:(SIGKILL) 51 | - kill -s SIGINT 52 | - logs: 53 | - port 54 | - ps 55 | - pull 56 | - restart 57 | - rm 58 | 59 | 60 | # Compose命令说明:run 61 | 62 | - docker-compose run web python manage.py shell 63 | - 自动创建volume 64 | - link容器也会被创建(--no-deps禁止自动创建) 65 | - 不会创建新的端口(--service-ports) 66 | 67 | # Compose命令说明: scale 68 | 69 | - docker-compose scale web=2 worker=3 70 | - 然并卵 71 | 72 | # Compose命令说明 73 | 74 | - start 75 | - stop 76 | - rm 77 | 78 | # Compose命令说明: up 79 | 80 | - 构建/创建/启动/attach到服务的容器中 81 | - 被Linked的服务会自动启动 82 | - -d 83 | - --no-recreate 84 | 85 | 86 | # 容器links 87 | 88 | - Compose使用容器links连接服务 89 | - docker-compose run SERVICE env 90 | 91 | # Compose参数说明:-f 92 | 93 | - -f -file 94 | - 默认 docker-compose.yml 95 | - 向上级文件夹递归查找 96 | 97 | # Compose参数说明:-p 98 | 99 | - -p, –project-name NAME 100 | - 默认为当前文件夹名。 101 | 102 | 103 | # Compose的环境变量 104 | 105 | - COMPOSE_PROJECT_NAME:默认为当前文件夹 106 | - COMPOSE_FILE:配置文件,默认为docker-compose.yml 107 | - DOCKER_HOST:默认为 unix:///var/run/docker.sock 108 | - DOCKER_TLS_VERIFY:非空为启用TLS 109 | - DOCKER_CERT_PATH:设置证书文件位置,默认为~/.docker 110 | 111 | 112 | # Compose配置文件说明 113 | 114 | 115 | - image 116 | - build 117 | - dockerfile 118 | - command 119 | 120 | # links 121 | 122 | - db 123 | - db:database 124 | - redis 125 | 126 | # external_links 127 | 128 | 129 | # extra_hosts 130 | 131 | - 等于--add-host参数 132 | - "somehost:162.242.195.82" 133 | - "otherhost:50.31.209.229" 134 | 135 | # ports 136 | 137 | - "3000" 138 | - "49100:22" 139 | - "127.0.0.1:8001:8001" 140 | - !!使用字符串形式 141 | 142 | # expose 143 | 144 | - expose但是不向host发布 145 | - 只能在linked服务中使用 146 | 147 | # volumes 148 | 149 | - /var/lib/mysql 150 | - cache/:/tmp/cache 151 | - ~/configs:/etc/configs/:ro 152 | 153 | # volumes_from 154 | 155 | - service_name 156 | - container_name 157 | 158 | # environment 159 | 160 | - RACK_ENV: development 161 | - SESSION_SECRET: 162 | 163 | 164 | # env_file 165 | 166 | - 值或者list的形式 167 | - env_file: .env 168 | 169 | 170 | # extends 171 | 172 | - 继承模板文件 173 | - 可以覆盖模板中的设置 174 | - extends: 175 | - file: common.yml 176 | - service: web 177 | 178 | # extends 179 | 180 | - links和volumes_from需要在本地定义 181 | - 单值属性(image/command): 覆盖 182 | 183 | # extends 多值属性 184 | 185 | - 串接: ports/expose/external_links/dns/dns_search 186 | - 按key merge: environment/labels 187 | - 按value merge: volumes/devices 188 | 189 | # labels 190 | 191 | - 容器的metadata 192 | - 建议使用DNS标记法以防冲突 193 | - com.example.description: "Accounting webapp" 194 | - "com.example.description=Accounting webapp" 195 | 196 | # log driver 197 | 198 | - 等于docker run --log-driver 199 | - 可以指定为json-file,syslog和none 200 | - 默认为json-file 201 | 202 | # net 203 | 204 | - 等于 docker run --net参数 205 | - net: "bridge" 206 | - net: "none" 207 | - net: "container:[name or id]" 208 | - net: "host" 209 | 210 | # 其他参数 211 | 212 | - dns, dns_search 213 | - pid 214 | - cap_add, cap_drop 215 | 216 | 217 | # 其他参数 218 | 219 | ```bash 220 | cap_add: 221 | - ALL 222 | cap_drop: 223 | - NET_ADMIN 224 | - SYS_ADMIN 225 | security_opt: 226 | - label:user:USER 227 | - label:role:ROLE 228 | ``` 229 | 230 | # 和docker run一样的参数 231 | 232 | - working_dir 233 | - entrypoint 234 | - user 235 | - hostname 236 | - mem_limit 237 | - privileged 238 | - restart 239 | - cpu_shares 240 | - cpuset 241 | 242 | 243 | # Docker Compose的局限 244 | 245 | - 面向单主机 246 | - 不能解决网络和存储问题 247 | 248 | # 课后作业 249 | 250 | - 运行同目录下的例子 251 | - 构建自己的应用栈:App + DB 252 | -------------------------------------------------------------------------------- /lesson-10/images/docker-machine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-10/images/docker-machine.png -------------------------------------------------------------------------------- /lesson-10/keynote.md: -------------------------------------------------------------------------------- 1 | # Docker入门与实践 2 | 3 | Lesson-10 Docker Machine 4 | 刘斌@Alauda 5 | 2015年8月 6 | 7 | # 本节概要 8 | 9 | - 什么是Docker Machine 10 | - 使用Machine创建Docker主机 11 | - 使用Machine在Digital Ocean上创建主机 12 | - Machine命令讲解 13 | 14 | # 什么是Docker Machine 15 | 16 | ![](../lesson-01/images/docker-machine-logo.png) 17 | 18 | # 背景 19 | 20 | - 大量服务的provisioning 21 | - 手工安装、升级的麻烦 22 | 23 | # Docker Machine 24 | 25 | - 创建Docker主机运行环境 26 | - 创建服务器 27 | - 配置Docker 28 | - 配置客户端环境变量 29 | 30 | # Docker Machine 31 | 32 | - 远程控制主机: 33 | - 启动、停止和重启 34 | - 升级Docker 35 | - 配置客户端环境变量以和Daemon通信 36 | 37 | # 实验操作环境 38 | 39 | - HOST: OS X 40 | - Driver: VirtualBox、Digital Ocean 41 | 42 | # 创建VirtualBox主机 43 | 44 | ```bash 45 | docker-machine create --driver virtualbox dev 46 | eval "$(docker-machine env dev)" 47 | docker run busybox echo hello world 48 | ``` 49 | 50 | # 在云主机上使用Docker Machine 51 | 52 | - 创建digitalocean token 53 | 54 | # 在云主机上使用Docker Machine 55 | 56 | ```bash 57 | docker-machine create \ 58 | --driver digitalocean \ 59 | --digitalocean-access-token xxxxxxxxxxx \ 60 | --digitalocean-image centos-7-0-x64 \ 61 | --digitalocean-region "sfo1" \ 62 | --digitalocean-size "512mb" \ 63 | do 64 | ``` 65 | 66 | # Digital Ocean 参数 67 | 68 | - --digitalocean-access-token 69 | - --digitalocean-image 70 | - --digitalocean-region 71 | - --digitalocean-size 72 | - --digitalocean-ipv6 73 | - --digitalocean-private-networking 74 | - --digitalocean-backups 75 | 76 | # 子命令说明:create 77 | 78 | - create 79 | - docker-machine create -d virtualbox 80 | 81 | # 子命令说明:create 82 | 83 | - --engine-insecure-registry registry.myco.com 84 | - --engine-registry-mirror 85 | - --engine-label 86 | - --engine-storage-driver 87 | 88 | # 子命令说明:create 89 | 90 | - --engine-opt dns=8.8.8.8 91 | - --engine-opt log-driver=syslog 92 | 93 | # 子命令说明:create 94 | 95 | - --swarm 96 | 97 | # 子命令说明:env 98 | 99 | - docker-machine env machinename 100 | - eval "$(docker-machine env machinename)" 101 | 102 | # 子命令说明:ls 103 | 104 | - docker-machine ls --filter driver=virtualbox --filter state=Running 105 | - driver(driver name) 106 | - swarm(swarm master’s name) 107 | - state(Running|Paused|Saved|Stopped|Stopping|Starting|Error) 108 | 109 | # 子命令说明:ssh 110 | 111 | - docker-machine ssh dev 112 | - docker-machine ssh dev COMMAND 113 | - docker-machine ssh dev -- df -h 114 | 115 | # 子命令说明:其他 116 | 117 | - start 118 | - stop 119 | - restart(=stop && start) 120 | - rm 121 | 122 | # 子命令说明:其他 123 | 124 | - inspect (-f) 125 | - ip 126 | - upgrade 127 | - scp 128 | 129 | 130 | # 子命令说明:其他 131 | 132 | - active 133 | - config 134 | - kill(强制停止) 135 | 136 | 137 | 138 | # 课后作业 139 | 140 | - 使用VirtualBox创建Docker主机 141 | - 有条件的话可以在云服务器上创建Docker主机 142 | 143 | -------------------------------------------------------------------------------- /lesson-11/keynote.md: -------------------------------------------------------------------------------- 1 | # Docker入门与实践 2 | 3 | Lesson-11 Docker Swarm 4 | 刘斌@Alauda 5 | 2015年8月 6 | 7 | # 本节概要 8 | 9 | - Swarm简介 10 | - 动手试用Swarm 11 | - Swarm深入讲解 12 | 13 | # 什么是Swarm 14 | 15 | Docker Swarm is native clustering for Docker. It allows you create and access to a pool of Docker hosts using the full suite of Docker tools. 16 | 17 | ![](../lesson-01/images/docker-swarm-logo.png) 18 | 19 | # Docker集群软件出现的背景 20 | 21 | - 应用架构变复杂 22 | - 高可用、大规模应用的普及 23 | - 资源池化 24 | 25 | # 什么是Swarm 26 | 27 | - 原生Docker集群 28 | - 跨主机创建容器 29 | - 兼容Docker Remote API 30 | - BETA中 31 | 32 | # 什么是Swarm 33 | 34 | - 资源抽象层 35 | - 原则:可交换,可插拔,通过API 36 | - 第三方或自己定制的调度组件 37 | 38 | # 架构 39 | 40 | - Manager 节点 41 | - Agent 节点 42 | 43 | # 实验环境 44 | 45 | - OS X 46 | - Docker Machine 47 | 48 | 49 | # 实验步骤 50 | 51 | - 拉取Swarm镜像 52 | - 通过swarm create获得集群id 53 | - 创建swarm集群(及master节点) 54 | - 创建集群Agent节点 55 | 56 | # Swarm组件解析 57 | 58 | - Discovery 59 | - Scheduler 60 | 61 | # 发现(Discovery)组件 62 | 63 | - 让节点能找到所要加入的集群 64 | 65 | # 发现组件的实现方式 66 | 67 | - 基于Docker Hub的发现服务 68 | - 静态文件(file参数) 69 | - etcd 70 | - consul 71 | - zookeeper 72 | - 静态服务器列表(nodes参数) 73 | - 定制Backends 74 | 75 | # 自定义服务发现 76 | 77 | - DiscoveryService接口 78 | - Initialize 79 | - Fetch 80 | - Watch 81 | - Register 82 | 83 | # Scheduler组件 84 | 85 | - Strategies 86 | - Filters 87 | 88 | # Strategies 89 | 90 | - Ranking(打分) 91 | - swarm manage --strategy 92 | 93 | # 目前支持的策略 94 | 95 | - spread(默认) 96 | - binpack 97 | - random 98 | 99 | # spread & binpack 100 | 101 | - 按照可用CPU、内存以及运行中容器数为节点打分 102 | - spread:最少容器运行 -> 容器平均分布 103 | - binpack:最拥挤 -> 避免碎片化,最大限度利用资源 104 | 105 | # Filters 106 | 107 | - Constraint 108 | - Affinity 109 | - Port 110 | - Dependency 111 | - Health 112 | 113 | # Constraint Filter 114 | 115 | - 指定某一节点 116 | - key-value tags 117 | - storage=ssd 118 | - storage=disk 119 | 120 | # Constraint Filter 121 | 122 | - docker -d --label storage=ssd 123 | - docker run -e constraint:storage==ssd 124 | 125 | # 标准约束Standard Constraints 126 | 127 | - node ID or node Name (using key “node”) 128 | - storagedriver 129 | - executiondriver 130 | - kernelversion 131 | - operatingsystem 132 | 133 | # 亲和度(Affinity)filter 134 | 135 | - 通过指定关系的亲密程度来选择节点 136 | - 指定容器或镜像 137 | - 或者label 138 | - 确保容器运行于同一网络节点上 139 | 140 | # Container affinity 141 | 142 | - 与指定的容器ID或name运行在同一节点 143 | 144 | # Container affinity 145 | 146 | ```bash 147 | docker run --name frontend 148 | docker run -e affinity:container==frontend 149 | ``` 150 | 151 | # Image affinity 152 | 153 | - -e affinity:image==redis 154 | - -e affinity:image==06a1f75304ba 155 | 156 | # Container Label affinity 157 | 158 | ```bash 159 | docker run --label com.example.type=frontend 160 | docker ps --filter "label=com.example.type=front" 161 | docker run -e affinity:com.example.type==frontend 162 | ``` 163 | 164 | # Filter表达式语法 165 | 166 | - constraint:node==node1 167 | - constraint:node!=node1 168 | - constraint:region!=us* 169 | - constraint:node==/node[12]/ 170 | - constraint:node==/node\d/ 171 | - constraint:node!=/node-[01]/ 172 | 173 | # Soft Affinities/Constraints 174 | 175 | - Affinities/Constraints 不满足,容器不会被启动 176 | - Soft Affinities/Constraints (~):不满足则丢弃约束 177 | - -e affinity:image==~redis 178 | - -e constraint:region==~us* 179 | - -e affinity:container!=~redis* 180 | 181 | # Port Filter 182 | 183 | - 因为Port是稀缺且排他的资源 184 | 185 | # Dependency Filter 186 | 187 | - 两个容器必须要在同一node工作 188 | - 如果不能找到满足条件的node,则拒绝创建新容器 189 | 190 | # Dependency Filter 类型 191 | 192 | - Volumes: --volumes-from=dependency 193 | - Links: --link=dependency:alias 194 | - Network stack: --net=container:dependency 195 | 196 | # Health Filter 197 | 198 | - 避免容器被分配到不健康的节点 199 | 200 | # 课后作业 201 | 202 | - 使用Docker Machine创建Swarm集群 203 | - 1个master,2个node 204 | 205 | 206 | -------------------------------------------------------------------------------- /lesson-12/images/cnm-model.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-12/images/cnm-model.jpg -------------------------------------------------------------------------------- /lesson-12/images/docker-turtles-communication.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-12/images/docker-turtles-communication.jpg -------------------------------------------------------------------------------- /lesson-12/images/docker_bridged.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-12/images/docker_bridged.png -------------------------------------------------------------------------------- /lesson-12/images/docker_container.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-12/images/docker_container.png -------------------------------------------------------------------------------- /lesson-12/images/etcd-ambassador-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-12/images/etcd-ambassador-flow.png -------------------------------------------------------------------------------- /lesson-12/images/flannel-packet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-12/images/flannel-packet.png -------------------------------------------------------------------------------- /lesson-12/images/flannel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-12/images/flannel.png -------------------------------------------------------------------------------- /lesson-12/images/socketplane.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-12/images/socketplane.png -------------------------------------------------------------------------------- /lesson-12/images/weave-arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-12/images/weave-arch.png -------------------------------------------------------------------------------- /lesson-12/keynote.md: -------------------------------------------------------------------------------- 1 | # Docker入门与实践 2 | 3 | Lesson-12 Docker网络 4 | 刘斌@Alauda 5 | 2015年8月 6 | 7 | # 本节概要 8 | 9 | - Linux网络基础 10 | - iptables基础知识 11 | - Docker的网络实现原理 12 | - Docker和网络相关的参数和配置bash 13 | - 对Docker进行简单的网络定制 14 | - 一些网络解决方案(SDN) 15 | 16 | # Linux 网络设备 17 | 18 | - eth0 19 | - lo 20 | - ip命令 21 | 22 | # Linux网络文件说明 23 | 24 | - /etc/hostname 25 | - /etc/hosts 26 | - /etc/resolv.conf 27 | 28 | # 演示1 29 | 30 | - 在容器内 31 | - ip addr show 32 | - 查看/etc/hostname 33 | - /etc/hosts 34 | - /etc/resolv.conf 35 | 36 | 37 | # iptables基础知识 38 | 39 | - 防火墙 40 | - NAT 41 | 42 | # iptables的4个表 43 | 44 | - filter 45 | - nat 46 | - mangle 47 | - raw 48 | 49 | # iptables的4个表 50 | 51 | ```bash 52 | $ sudo iptables -t filter -L 53 | ``` 54 | 55 | # Docker中的网络 56 | 57 | - Network NS 58 | - iptables 59 | - 网桥 60 | 61 | # docker0网桥 62 | 63 | - 172.17.42.1/16 64 | - 16bit的网络,有65534个地址可用 65 | - 连接host和所有容器的虚拟子网 66 | 67 | # Docker容器运行的4种网络模式 68 | 69 | - bridge 70 | - host 71 | - 容器 72 | - overlay(实验版) 73 | - none 74 | 75 | # bridge模式 76 | 77 | - --net=bridge 78 | - 默认模式。172段IP地址。 79 | 80 | ![](./images/docker_bridged.png) 81 | 82 | 图片来源:http://blog.midonet.org/docker-networking-midonet/ 83 | 84 | # host 85 | 86 | - --net=host 87 | - 共享主机IP地址、网卡设备、主机名等。 88 | 89 | # 容器模式 90 | 91 | - --net=container:(id/name) 92 | - 共享其他容器网络环境 93 | 94 | ![](./images/docker_container.png) 95 | 96 | 图片来源:http://blog.midonet.org/docker-networking-midonet/ 97 | 98 | # none无网络模式 99 | 100 | - --net=none 101 | - 容器启动时,无任何网络。 102 | - 可手工配,适用于需要对网络结构进行特殊定制的情形。 103 | 104 | # docker run 参数 105 | 106 | - docker run -h hostname 107 | - --dns-search=192.168.10.100 108 | - docker run -d -p 8080:8080 109 | 110 | 111 | # -p和-P参数 112 | 113 | - -P 随机分配宿主机端口,49000~49900 114 | - -p 详细配置端口映射 115 | - - 8080:80 116 | - 127.0.0.1:8080:80 117 | - 127.0.0.1::80 118 | 119 | # docker port查看端口映射 120 | 121 | - docker port 80 122 | 123 | # 和网络相关的命令行参数 124 | 125 | - 只能在daemon中使用 126 | - 只能在client中使用 127 | - 在daemon和client中都能使用 128 | 129 | # 只能在daemon中使用的参数 130 | 131 | - -b BRIDGE or --bridge=BRIDGE 132 | - --bip=CIDR 133 | - --default-gateway=IP_ADDRESS 134 | - --fixed-cidr 135 | - --default-gateway-v6=IP_ADDRESS 136 | 137 | - -H SOCKET... or --host=SOCKET... daemon监听接口 138 | - --icc=true|false 139 | - --ip=IP_ADDRESS 140 | - --ip-forward=true|false 141 | 142 | - --iptables=true|false 143 | - --mtu=BYTES 144 | --userland-proxy=true|false 145 | 146 | # 只能在docker run中使用 147 | 148 | - -h HOSTNAME or --hostname=HOSTNAME 149 | - --link=CONTAINER_NAME_or_ID:ALIAS 150 | - --net=bridge|none|container:NAME_or_ID|host 151 | - --mac-address=MACADDRESS... 152 | - -p SPEC or --publish=SPEC 153 | - -P or --publish-all=true|false 154 | 155 | 156 | # 在client和daemon都能使用 157 | 158 | - --dns=IP_ADDRESS 159 | - --dns-search=DOMAIN 160 | 161 | 162 | # /etc下的三个关键文件 163 | 164 | ```bash 165 | mount | grep /etc 166 | 167 | /dev/vda1 on /etc/resolv.conf type ext4 (rw,relatime,data=ordered) 168 | /dev/vda1 on /etc/hostname type ext4 (rw,relatime,data=ordered) 169 | /dev/vda1 on /etc/hosts type ext4 (rw,relatime,data=ordered) 170 | ``` 171 | 172 | # hostname和hosts 173 | 174 | - -h HOSTNAME or --hostname=HOSTNAME 175 | - /etc/hostname 176 | - /etc/hosts 177 | - shell提示符 178 | 179 | # hostname和hosts 180 | 181 | - --link=CONTAINER_NAME_or_ID:ALIAS 182 | - /etc/hosts 中添加 ALIAS 183 | - ALIAS重启后,自动更新/etc/hosts 184 | 185 | # resolv.conf 186 | 187 | - --dns=IP_ADDRESS... 188 | - /etc/resolv.conf添加server行 189 | - --dns-search=DOMAIN... 190 | - 在/etc/resolv.conf添加search行 191 | 192 | # 容器通信 193 | 194 | - 容器之间 195 | - 容器访问外部 196 | - 外部访问容器 197 | 198 | # 容器和外部通信 199 | 200 | - host是否允许包转发 201 | - iptables是否允许容器间连接 202 | 203 | # host上的包转发 204 | 205 | - ip_forward ,设置1时容器间可以通信 206 | - --ip-forward=true一样效果 207 | 208 | # host上的包转发 209 | 210 | ```bash 211 | # sysctl net.ipv4.conf.all.forwarding=1 212 | # sysctl net.ipv4.conf.all.forwarding 213 | net.ipv4.conf.all.forwarding = 1 214 | ``` 215 | 216 | # Docker iptables设置 217 | 218 | - --iptables=false,Docker不会进行iptables设置 219 | - 默认会在DOCKER过滤链中添加规则 220 | 221 | # 容器间通信 222 | 223 | - 网络拓扑结构上是否能互通 224 | - iptables是否允许(--icc=true) 225 | - 在FORWARD链添加ACCEPT策略 226 | - --icc=false. 则为DROP 227 | 228 | # icc=false时容器如何互连? 229 | 230 | - --icc=true,安全性问题 231 | - 使用link可以解决 232 | - --icc=false 并且 --iptables=true 233 | 234 | # 外部如何连接到容器? 235 | 236 | - iptables masquerade 规则 237 | - 运行容器访问外部世界 238 | 239 | # 外部如何连接到容器? 240 | 241 | ```bash 242 | iptables -t nat -L -n 243 | Chain POSTROUTING (policy ACCEPT) 244 | target prot opt source destination 245 | MASQUERADE all -- 172.17.0.0/16 0.0.0.0/0 246 | ``` 247 | 248 | # 外部如何连接到容器? 249 | 250 | - 使用-P或者--publish-all=true,EXPOSE所有Dockerfile里的端口 251 | - --expose <端口号> 252 | - 映射到host端口上 253 | - host端口范围由/proc/sys/net/ipv4/ip_local_port_range 控制 254 | - 一般为 32768 to 61000 255 | 256 | # -p和-P的区别 257 | 258 | - -p 小p是精确映射 259 | - -P expose出全部镜像定义的端口 260 | 261 | 262 | # -P(大P)时iptables规则 263 | 264 | ```bash 265 | iptables -t nat -L -n 266 | Chain DOCKER (2 references) 267 | target prot opt source destination 268 | DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:49153 to:172.17.0.2:80 269 | ``` 270 | 271 | # -p(小p)时iptables规则 272 | 273 | ```bash 274 | Chain DOCKER (2 references) 275 | target prot opt source destination 276 | DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 to:172.17.0.2:80 277 | ``` 278 | 279 | # 定制docker0 280 | 281 | - --bip=CIDR —docker0网桥IP地址,CIDR格式,如192.168.1.5/24 282 | - --fixed-cidr=CIDR—IP范围 docker0子网, like 172.167.1.0/28 283 | - --mtu=BYTES docker0的最大传输单元大小 284 | 285 | 286 | # 容器启动时所做的网络工作 287 | 288 | - 在host中创建虚拟设备对vethXXXX 289 | - 将vethXXXX绑定到docker0网桥 290 | - 将设备对的另一端放入容器,命名为eth0 291 | - 独立网络namespace,不用担心各种冲突 292 | - 为eth0设置mac(用户可指定)和IP地址(不能指定) 293 | - 默认路由为docker0网桥的IP地址 294 | 295 | # 模拟Docker网络设置过程 296 | 297 | - 实验演示 298 | - 模拟Docker为容器创建网络设备 299 | 300 | # 创建点对点连接 301 | 302 | - 虚拟设备对从host-container到container-container 303 | - 配置为点对点连接 304 | - 可和其他网络模式并用 305 | 306 | # 然而需求源源不断 307 | 308 | - IP重用 309 | - 任意指定IP 310 | - 跨主机通信 311 | - 从外部直接访问容器网路 312 | - L2/L3跨主机虚拟网络 313 | 314 | 315 | # pipework 316 | 317 | - Jérôme Petazzoni,Docker公司布道师 318 | - https://github.com/jpetazzo/pipework 319 | - ip/brctl/ovs-vsctl 320 | - VLAN/macvlan/Open vSwitch 321 | - DHCP 322 | 323 | # 修改容器内网络配置文件 324 | 325 | - /etc/hosts,/etc/hostname,/etc/resolve.conf 326 | - 只能在running的容器中 327 | - docker commit 不能保存 328 | - docker restart 也会丢失 329 | 330 | # libnetwork 331 | 332 | - SocketPlane 333 | - 2015.3被Docker inc.收购 334 | - Multi-Host Container Networking 335 | 336 | ![](./images/socketplane.png) 337 | 338 | # libnetwork 339 | 340 | - 跨平台的容器网络库 341 | - libcontainer的网络版 342 | - 轻量、高模块化、可组装、独立工作的工具 343 | - “batteries included but swappable” 344 | 345 | ![](./images/docker-turtles-communication.jpg) 346 | 347 | # CNM组件 348 | 349 | - Container Network Model (CNM)实现 350 | - Sandbox(网络栈配置,Linux Network NS ) 351 | - Endpoint(将Sandbox连接到Network,veth) 352 | - Network(一组可以互相通信的Endpoint,Linux网桥/VLAN) 353 | 354 | # CNM组件 355 | 356 | ![](./images/cnm-model.jpg) 357 | 358 | # CNM对象(Objects) 359 | 360 | - NetworkController 361 | - Driver 362 | - Network 363 | - Endpoint(Service Endpoint) 364 | - Sandbox 365 | 366 | # Drivers 367 | 368 | - null 369 | - bridge 370 | - overlay(实验版experimental) 371 | - remote 372 | 373 | # 第三方网络解决方案 374 | 375 | - weave 376 | - flannel 377 | - Calico 378 | - Triton 379 | 380 | # weave 381 | 382 | - Weaveworks开发 383 | - 高效的连接、监视和控制Docker容器的方式 384 | 385 | # weave 386 | 387 | - virtual network 388 | - 跨主机、自动发现 389 | - 不需要配置link,端口映射等 390 | - 轻松对外发布weave network上的服务 391 | 392 | ![](images/weave-arch.png) 393 | 394 | # flannel 395 | 396 | - CoreOS开发 397 | - 基于etcd的容器网络编配 398 | - Agent: flanneld 399 | 400 | # flannel 401 | 402 | ![](images/flannel-packet.png) 403 | 404 | # flannel Backends 405 | 406 | - udp 407 | - vxlan 408 | - host-gw 409 | - aws-vpc 410 | - gce 411 | - alloc 412 | 413 | 414 | # 课后作业 415 | 416 | - 练习iptables命令 417 | - 使用--net=host启动容器,查看网络配置 418 | - 使用--net=container启动容器,查看网络配置 419 | - 使用--net=none,手工为容器配置网络 420 | -------------------------------------------------------------------------------- /lesson-13/README.md: -------------------------------------------------------------------------------- 1 | # Lesson-13 Docker CaaS 2 | 3 | # 网址 4 | 5 | - 国内线路: http://www.alauda.cn/ 6 | - 国际线路: http://www.alauda.io/ 7 | 8 | # 安装命令行工具 9 | 10 | ## 安装pip 11 | 12 | ``` 13 | wget https://bootstrap.pypa.io/get-pip.py 14 | sudo python get-pip.py 15 | ``` 16 | 17 | ## 安装alauda命令行工具 18 | 19 | ``` 20 | sudo yum install -y python-devel libffi-devel openssl-devel 21 | sudo pip install alauda 22 | ``` 23 | 在执行任何命令的时候,如果出现警告: 24 | 25 | ``` 26 | InsecurePlatformWarning: A true SSLContext object is not available. This prevents urllib3 from configuring SSL appropriately and may cause certain SSL connections to fail. For more information, see https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning. 27 | ``` 28 | 可以尝试: 29 | 30 | ``` 31 | sudo pip install pyopenssl ndg-httpsclient pyasn1 32 | ``` 33 | 34 | 来解决这个问题。 35 | 36 | # 实验 37 | 38 | 39 | ## 基本命令 40 | 41 | ``` 42 | $ alauda login 43 | $ alauda service inspect blog 44 | $ alauda ps 45 | 46 | 47 | $ alauda stop db1 48 | $ alauda service instances blog 49 | 50 | $ alauda rm db1 51 | $ alauda rm blog 52 | ``` 53 | 54 | ## Alauda Compose 55 | 56 | ``` 57 | alauda compose up 58 | 59 | alauda ps 60 | 61 | ``` 62 | 63 | 64 | ## 备份数据卷 65 | 66 | ``` 67 | select * from wp_options limit 2; 68 | ``` 69 | 70 | 71 | # 参考链接 72 | 73 | - Alauda主页 74 | 75 | http://www.alauda.cn/ 76 | 77 | - Alauda文档中心 78 | 79 | http://docs.alauda.cn/ 80 | 81 | - Alauda命令行 82 | 83 | http://docs.alauda.cn/ 84 | 85 | 86 | # 视频地址 87 | 88 | * [灵雀云简介](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2747) 89 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker28.jpg) 90 | * [使用灵雀云命令行工具](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2748) 91 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker29.jpg) 92 | 93 | -------------------------------------------------------------------------------- /lesson-13/docker-compose.yml: -------------------------------------------------------------------------------- 1 | wordpress: 2 | image: index.alauda.cn/library/wordpress:3 3 | links: 4 | - db:mysql 5 | ports: 6 | - "80/http" 7 | environment: 8 | - WORDPRESS_DB_PASSWORD: password 9 | volumes: 10 | - /var/www/html:10 11 | size: M 12 | 13 | db: 14 | image: index.alauda.cn/library/mysql:5 15 | ports: 16 | - "3306/tcp" 17 | environment: 18 | - MYSQL_ROOT_PASSWORD: password 19 | volumes: 20 | - /var/lib/mysql:10 21 | size: M 22 | -------------------------------------------------------------------------------- /lesson-13/keynote.md: -------------------------------------------------------------------------------- 1 | # Docker入门与实践 2 | 3 | Lesson-13 Docker CaaS 4 | 刘斌@Alauda 5 | 2015年8月 6 | 7 | # 本节概要 8 | 9 | - 什么是CaaS 10 | - 灵雀云功能简介 11 | - 使用灵雀云创建有状态服务 12 | - 数据备份和恢复 13 | - alauda命令行工具介绍 14 | 15 | # 什么是CaaS 16 | 17 | - 容器即服务 18 | - 托管镜像,而不是代码 19 | 20 | # CaaS的优势 21 | 22 | - 服务于完整开发周期 23 | - 优化开发-运维整体流程 24 | - 提高产品开发迭代速度,缩短交付周期 25 | - 高可用、高性能、高密度、高动态的容器服务 26 | - 降低IT成本 27 | 28 | # 灵雀云基本功能 29 | 30 | - 镜像加速 31 | - 共有、私有镜像托管 32 | - 容器托管 33 | - 一键部署,自动修复、扩展 34 | - 镜像市场 35 | - 国内外数据中心 36 | 37 | # 灵雀云特色功能 38 | 39 | - 持久存储卷(Persistent Storage Volume) 40 | - 存储卷备份(Storage Volume Backup) 41 | - 内部通信(Internal Endpoint) 42 | 43 | # 灵雀云特色功能 44 | 45 | - 跨主机容器关联,四层、七层负载均衡 46 | - 灵雀云命令行(Alauda CLI),一键发布任何容器化应用 47 | - Alauda Compose 48 | - EXEC 49 | 50 | # alauda _EXEC 51 | 52 | - docker exec on Web 53 | 54 | # 使用灵雀云创建有状态服务 55 | 56 | - 什么是有状态服务 57 | - 创建Wordpress网站 58 | 59 | # 数据备份和恢复 60 | 61 | - 备份数据库文件 62 | - 以备份文件创建新服务 63 | 64 | # alauda命令行工具介绍 65 | 66 | - Python编写,开源 67 | - pip install 68 | 69 | # alauda命令 70 | 71 | - alauda ps 72 | - alauda stop 73 | - alauda rm 74 | - alauda service 75 | 76 | # alauda compose 77 | 78 | - 兼容Docker Compose语法 79 | - alauda compose up 80 | - alauda compose ps 81 | - alauda compose start 82 | - alauda compose rm 83 | 84 | # alauda compose 85 | 86 | - 创建Wordpress应用 87 | 88 | 89 | # 课后作业 90 | 91 | - 试用alauda.cn 92 | - 创建有状态容器 93 | - 使用volume 94 | - 进行volume的备份和恢复 95 | 96 | -------------------------------------------------------------------------------- /lesson-14/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM centos:7 2 | 3 | MAINTAINER bin liu 4 | 5 | RUN yum update -y 6 | 7 | # 安装Java和Git 8 | RUN yum install -y java-1.8.0-openjdk git 9 | 10 | ENV JENKINS_HOME /opt/jenkins/data 11 | ENV JENKINS_MIRROR http://mirrors.jenkins-ci.org 12 | 13 | # 下载Jenkins的war包 14 | RUN mkdir -p $JENKINS_HOME/plugins 15 | RUN curl -sf -o /opt/jenkins/jenkins.war -L $JENKINS_MIRROR/war-stable/latest/jenkins.war 16 | 17 | # 安装Jenkins插件 18 | RUN for plugin in chucknorris greenballs scm-api git-client git ws-cleanup ;\ 19 | do curl -sf -o $JENKINS_HOME/plugins/${plugin}.hpi \ 20 | -L $JENKINS_MIRROR/plugins/${plugin}/latest/${plugin}.hpi ; done 21 | 22 | EXPOSE 8080 23 | 24 | # 添加启动命令 25 | CMD ["java", "-jar", "/opt/jenkins/jenkins.war"] 26 | -------------------------------------------------------------------------------- /lesson-14/README.md: -------------------------------------------------------------------------------- 1 | # Lesson-14 基于Docker进行CI(持续集成) 2 | 3 | 4 | # 构建Jenkins镜像 5 | 6 | 7 | ``` 8 | sudo docker build -t "jenkins" . 9 | 10 | ``` 11 | 12 | # 启动Jenkins 13 | 14 | ``` 15 | sudo mkdir -p /opt/jenkins/data/workspace 16 | 17 | jk=$(sudo docker run -d --net=host -v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker -v /sys:/sys -v /lib64:/lib64 -v /var/lib/docker:/var/lib/docker -v /opt/jenkins/data/workspace:/opt/jenkins/data/workspace --privileged -p 8080:8080 jenkins) 18 | 19 | sudo docker logs -f $jk 20 | ``` 21 | 22 | # 创建Jenkins任务 23 | 24 | - 打开Jenkins http://localhost:8080 25 | 26 | - 创建一个任务,选择Freestyle project,点击下一步 27 | 28 | - Source Code Management 中选git,输入 https://github.com/liubin/docker101-sample-gem ,涉及到认证关系,这里不能输入git://github.com。。。 29 | 30 | - 下面的Build - build step中,选择Execute shell,内容如下: 31 | 32 | ``` 33 | # 这里构建镜像,将镜像id保存到IMAGE变量中 34 | IMAGE=$(docker build . | tail -1 | awk '{ print $NF }') 35 | 36 | # 启动容器,容器ID放到CONTAINER中 37 | CONTAINER=$(docker run -d -v "$WORKSPACE:/opt/project" $IMAGE /bin/bash -c "cd /opt/project && rake spec") 38 | 39 | # 取得容器的返回值(正常退出为0) 40 | RC=$(docker wait $CONTAINER) 41 | 42 | # 测试结束后删除容器 43 | docker rm $CONTAINER 44 | 45 | 46 | # 镜像可根据情况选择是否删除 47 | docker rmi -f $IMAGE 48 | 49 | # 返回值传回给Jenkins 50 | exit $RC 51 | 52 | ``` 53 | 54 | - Post-build Actions 中选择Publish JUnit test result report,输入 spec/reports/*.xml 。 55 | 56 | - 点击左边的Build Now开始构建 57 | 58 | - http://localhost:8080/job/test/1/console 查看console输出 59 | 60 | # 对docker101-sample-gem进行测试 61 | 62 | - https://github.com/liubin/docker101-sample-gem 63 | 64 | 65 | # 删除Jenkins容器 66 | 67 | ``` 68 | sudo docker kill $jk 69 | ``` 70 | 71 | 72 | # 视频地址 73 | 74 | * [基于Docker进行持续集成](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2749) 75 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker30.jpg) 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /lesson-14/images/jenkins_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-14/images/jenkins_logo.png -------------------------------------------------------------------------------- /lesson-14/keynote.md: -------------------------------------------------------------------------------- 1 | # Docker入门与实践 2 | 3 | Lesson-14 基于Docker进行CI(持续集成) 4 | 刘斌@Alauda 5 | 2015年8月 6 | 7 | # 本节概要 8 | 9 | - 什么是CI和Jenkins 10 | - 普通CI的流程 11 | - 如何使用Docker + Jenkins进行CI 12 | 13 | # 测试需求 14 | 15 | - 频繁进行 16 | - 干净环境 17 | - 打包安装费时 18 | - 环境复杂 19 | - 自动化 20 | - 持续交付 21 | 22 | # 什么是CI(Continuous Integration) 23 | 24 | - 持续集成 25 | - 早集成,常集成 26 | 27 | # 在CI中使用Docker的优势 28 | 29 | - 轻量快速 30 | - 可复用(Dockerfile,镜像) 31 | - 隔离(干净环境) 32 | 33 | # Jenkins简介 34 | 35 | - 开源CI服务 36 | - SCM/部署 37 | - plugin 38 | - war文件发布,不需要数据库 39 | - Web界面配置 40 | - email通知 41 | - 生成JUnit/TestNG报告 42 | - 分布式构建支持 43 | 44 | ![](./images/jenkins_logo.png) 45 | 46 | # Jenkins + Docker 模式 47 | 48 | - Git hook -> Jenkins -> Build Docker 镜像-> 测试 49 | - 不仅仅是效率的提升,更是一种变革 50 | - DevOps紧密结合 51 | 52 | # Jenkins + Docker 53 | 54 | - Jenkins和测试都跑在容器中 55 | - Docker in Docker 56 | 57 | # Jenkins + Docker 58 | 59 | ```bash 60 | a=$(sudo docker run -d --net=host -v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker -v /sys:/sys -v /lib64:/lib64 -p 8080:8080 j4) 61 | ``` 62 | 63 | # 实验 64 | 65 | - 在Docker中使用Jenkins进行测试 66 | 67 | # 课后作业 68 | 69 | - 运行本示例代码 70 | 71 | -------------------------------------------------------------------------------- /lesson-15/README.md: -------------------------------------------------------------------------------- 1 | # Lesson-15 延伸阅读 2 | 3 | # 网络 4 | 5 | ## weave 6 | 7 | https://github.com/weaveworks/weave 8 | 9 | ## Pipework 10 | 11 | https://github.com/jpetazzo/pipework 12 | 13 | ## flannel 14 | 15 | https://github.com/coreos/flannel 16 | 17 | 18 | 19 | # 存储 20 | 21 | ## Flocker 22 | 23 | * Container Data Volume Manager 24 | 25 | https://github.com/ClusterHQ/flocker 26 | 27 | 28 | # PaaS 29 | 30 | ## Flynn 31 | 32 | https://flynn.io/ 33 | 34 | ## Deis 35 | 36 | - https://github.com/deis/deis 37 | 38 | - http://deis.io/ 39 | 40 | 41 | # 编排 42 | 43 | ## Mesos 44 | 45 | http://mesos.apache.org/ 46 | 47 | ## Kubernetes(K8s) 48 | 49 | https://github.com/kubernetes/kubernetes 50 | 51 | # CI 52 | 53 | ## Drone 54 | 55 | https://drone.io/ 56 | 57 | # 容器OS 58 | 59 | ## RancherOS 60 | 61 | http://rancher.com/rancher-os/ 62 | 63 | ## CoreOS 64 | 65 | https://coreos.com/ 66 | 67 | ## Project Atomic 68 | 69 | http://www.projectatomic.io/ 70 | 71 | ## Hyper 72 | 73 | https://hyper.sh/ 74 | 75 | ## VMware Photon 76 | 77 | ## LXD 78 | 79 | http://www.ubuntu.com/cloud/tools/lxd 80 | 81 | ## Clear Linux/Clear Containers 82 | 83 | https://clearlinux.org/features/clear-containers 84 | 85 | # UI管理 86 | 87 | ## seagull 88 | 89 | https://github.com/tobegit3hub/seagull 90 | 91 | ## dockerui 92 | 93 | https://github.com/crosbymichael/dockerui 94 | 95 | # 其他容器技术 96 | 97 | ## OCI( Open Container Initiative) 98 | 99 | https://www.opencontainers.org/ 100 | 101 | ## RunC 102 | 103 | http://runc.io/ 104 | 105 | # 视频地址 106 | 107 | * [网络、存储和PaaS平台](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2750) 108 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker31.jpg) 109 | * [容器OS和容器标准化](http://www.kaikeba.com/kkb/kaikeba/content_video.html?vId=2751) 110 | ![](http://video.kk8.cdn.bj.xs3cnc.com/2c/i/covers/Docker32.jpg) 111 | 112 | -------------------------------------------------------------------------------- /lesson-15/images/coreos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-15/images/coreos.png -------------------------------------------------------------------------------- /lesson-15/images/deis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-15/images/deis.png -------------------------------------------------------------------------------- /lesson-15/images/etcd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-15/images/etcd.png -------------------------------------------------------------------------------- /lesson-15/images/flannel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-15/images/flannel.png -------------------------------------------------------------------------------- /lesson-15/images/fleet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-15/images/fleet.png -------------------------------------------------------------------------------- /lesson-15/images/flocker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-15/images/flocker.png -------------------------------------------------------------------------------- /lesson-15/images/hyper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-15/images/hyper.png -------------------------------------------------------------------------------- /lesson-15/images/k8s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-15/images/k8s.png -------------------------------------------------------------------------------- /lesson-15/images/lxd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-15/images/lxd.png -------------------------------------------------------------------------------- /lesson-15/images/mesos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-15/images/mesos.png -------------------------------------------------------------------------------- /lesson-15/images/rkt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-15/images/rkt.png -------------------------------------------------------------------------------- /lesson-15/images/runc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liubin/docker101/f59654ce717b86a05590e5b4cb11248175446455/lesson-15/images/runc.png -------------------------------------------------------------------------------- /lesson-15/keynote.md: -------------------------------------------------------------------------------- 1 | # Docker入门与实践 2 | 3 | Lesson-15 延伸阅读 4 | 刘斌@Alauda 5 | 2015年8月 6 | 7 | # 本节概要 8 | 9 | - 总结本系列课程 10 | - Docker的扩展知识 11 | - Docker的生态环境 12 | 13 | # 四大问题 14 | 15 | - 存储 16 | - 网络 17 | - 编配(集群管理) 18 | - 工作流 19 | 20 | # 解决方式 21 | 22 | - Docker自身的进化 23 | - 生态系统 24 | - 软件架构、工作流的进化 25 | 26 | # Docker产品 27 | 28 | - 编排 29 | - DevOps 30 | 31 | # 生态系统 32 | 33 | - There is no platform without ecosystem. 34 | - by Solomon Hykes @DockerCon2015 35 | 36 | # 存储 37 | 38 | - Flocker 39 | 40 | ![](./images/flocker.png) 41 | 42 | # PaaS 43 | 44 | - Dokku 45 | - Deis 46 | - Flynn 47 | 48 | # Deis 49 | 50 | ![](./images/deis.png) 51 | 52 | # 编排 53 | 54 | - Mesos 55 | - Kubernetes 56 | 57 | # 管理界面 58 | 59 | - docker-ui 60 | - openstack horizon 61 | - shipyard 62 | - Portus 63 | 64 | # 配置管理 65 | 66 | - chef 67 | - puppet 68 | - salt 69 | - Ansible 70 | 71 | # CI 72 | 73 | - jenkins 74 | - drone 75 | - strider 76 | - travis 77 | 78 | 79 | # 容器OS 80 | 81 | - CoreOS 82 | - Project Atomic 83 | - Hyper 84 | - http://rancher.com/ 85 | 86 | # rkt(Rocket) 87 | 88 | - App Container runtime for Linux 89 | - CoreOS主导开发 90 | - "rock-it" 91 | 92 | ![](images/rkt.png) 93 | 94 | # rkt特点 95 | 96 | - 没有daemon和Registry 97 | - 深度集成init(systemd,upstart) 98 | - 编配工具(fleet,k8s) 99 | - 兼容Docker镜像 100 | - 模块化、可扩展 101 | 102 | # LXD 103 | 104 | - Canonical 主导 105 | - 基于LXC,有daemon,REST API 106 | - lxc为客户端 107 | - OpenStack Nova plugin (nova-compute-lxd) 108 | - live migration 109 | 110 | ![](images/lxd.png) 111 | 112 | # 开放容器组织 113 | 114 | - OCI( Open Container Initiative, https://www.opencontainers.org/ ) 115 | - RunC( http://runc.io/ ) 116 | 117 | # RunC 118 | 119 | - Runtime 120 | - 基于libcontainer 121 | - 没有Daemon 122 | - 没有镜像管理但兼容Docker镜像 123 | 124 | ![](./images/hamster.png) 125 | 126 | 127 | --------------------------------------------------------------------------------