Docker
是个划时代的开源项目,它完全释放了计算虚拟化的威力,极大提升了应用的运行效率,下降了云计算资源供应的成本!使用 Docker
,可让应用的部署、测试和分发都变得史无前例的高效和轻松!php
不管是应用开发者、运维人员、仍是其余信息技术从业人员,都有必要认识和掌握 Docker
,节约有限的时间。html
要安装Docker CE
,您须要这些Ubuntu
版本的64位版本:node
Ubuntu x86_64,Linux armhf,s390x(IBM Z)和ppc64le(IBM Power)架构上支持Docker CE
。python
老版本的Docker
被称为docker
或docker-engine
。若是安装了这些,请将其卸载:mysql
$ apt-get remove docker docker-engine docker.io
首次在新的主机上安装Docker CE
以前,须要设置Docker
存储库。以后,您能够从存储库安装和更新Docker
。linux
1.更新apt
软件包索引:nginx
$ apt-get update
2.安装软件包以容许apt
经过HTTPS
使用存储库:git
$ apt-get install \ apt-transport-https \ ca-certificates \ curl \ software-properties-common
3.添加Docker
的官方GPG
密钥:github
鉴于国内网络问题,强烈建议使用国内源,官方源请在注释中查看。golang
$ curl -fsSL https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg | sudo apt-key add - # 官方源 # $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
4.添加 Docker 软件源
鉴于国内网络问题,强烈建议使用国内源,官方源请在注释中查看。
而后,咱们须要向 source.list
中添加 Docker
软件源
$ sudo add-apt-repository \ "deb [arch=amd64] https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu \ $(lsb_release -cs) \ stable" # 官方源 # $ sudo add-apt-repository \ # "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ # $(lsb_release -cs) \ # stable"
以上命令会添加稳定版本的 Docker CE APT
镜像源,若是须要最新或者测试版本的 Docker CE
请将 stable
改成 edge
或者 test
。从 Docker 17.06
开始,edge test
版本的 APT
镜像源也会包含稳定版本的 Docker
。
1.更新apt软件包索引。
$ apt-get update
2.安装最新版本的Docker CE,或者转到下一步安装特定版本。任何现有的Docker安装都将被替换。
$ apt-get install docker-ce
3.在生产系统上,您应该安装特定版本的Docker CE,而不是始终使用最新版本。此输出被截断。列出可用的版本。
$ apt-cache madison docker-ce docker-ce | 17.12.0~ce-0~ubuntu | https://download.docker.com/linux/ubuntu zesty/stable amd64 Packages docker-ce | 17.09.1~ce-0~ubuntu | https://download.docker.com/linux/ubuntu zesty/stable amd64 Packages docker-ce | 17.09.0~ce-0~ubuntu | https://download.docker.com/linux/ubuntu zesty/stable amd64 Packages docker-ce | 17.06.2~ce-0~ubuntu | https://download.docker.com/linux/ubuntu zesty/stable amd64 Packages docker-ce | 17.06.1~ce-0~ubuntu | https://download.docker.com/linux/ubuntu zesty/stable amd64 Packages docker-ce | 17.06.0~ce-0~ubuntu | https://download.docker.com/linux/ubuntu zesty/stable amd64 Packages
列表的内容取决于启用了哪一个存储库。选择一个特定的版本进行安装。第二列是版本字符串。第三列是存储库名称,它指出了软件包来自哪一个存储库,并经过扩展其稳定性级别。要安装特定版本,请将版本字符串附加到包名称,并用等号(=)将它们分开:
$ sudo apt-get install docker-ce=<VERSION>
4.经过运行hello-world
映像验证是否正确安装了Docker CE
。
$ docker run hello-world
这个命令下载一个测试图像并在容器中运行。容器运行时,会打印一条信息消息并退出。
Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world ca4f61b1923c: Pull complete Digest: sha256:445b2fe9afea8b4aa0b2f27fe49dd6ad130dfe7a8fd0832be5de99625dad47cd Status: Downloaded newer image for hello-world:latest Hello from Docker! This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. (amd64) 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal. To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash Share images, automate workflows, and more with a free Docker ID: https://cloud.docker.com/ For more examples and ideas, visit: https://docs.docker.com/engine/userguide/
默认状况下,docker
命令会使用 Unix socket
与 Docker
引擎通信。而只有 root
用户和 docker
组的用户才能够访问 Docker
引擎的 Unix socket
。出于安全考虑,通常 Linux
系统上不会直接使用 root
用户。所以,更好地作法是将须要使用 docker
的用户加入 docker
用户组。
要建立docker
组并添加您的用户:
1.建立docker组。
$ sudo groupadd docker
2.将您的用户添加到docker组中。
$ sudo usermod -aG docker $USER
3.注销并从新登陆,若是在虚拟机上进行测试,则可能须要从新启动虚拟机才能使更改生效。
4.验证您能够不运行docker
命令sudo
。
$ docker run hello-world
1.卸载Docker CE
软件包:
$ sudo apt-get purge docker-ce
2.主机上的图像,容器,卷或自定义配置文件不会自动删除。删除全部图像,容器和卷:
$ sudo rm -rf /var/lib/docker
这条命令会用nginx
镜像启动一个容器,命名为 myweb
,而且映射了 80
端口,这样咱们能够用浏览器去访问这个 nginx
服务器。
$ docker run --name myweb -d -p 80:80 nginx
直接访问:http://localhost;若是使用的是 Docker Toolbox,或者是在虚拟机、云服务器上安装的 Docker,则须要将 localhost 换为虚拟机地址或者实际云服务器地址。
如今,假设咱们很是不喜欢这个欢迎页面,咱们但愿改为欢迎 Docker
的文字,咱们可使用 docker exec
命令进入容器,修改其内容。
$ docker exec -it myweb bash root@5ceb0c8274ca:/# echo '<h1>Welcome to Docker!</h1>' > /usr/share/nginx/html/index.html root@5ceb0c8274ca:/# exit exit
直接访问:http://localhost;
咱们修改了容器的文件,也就是改动了容器的存储层。咱们能够经过 docker diff
命令看到具体的改动。COMMENT
列有备注!
$ docker diff myweb C /root A /root/.bash_history C /run A /run/nginx.pid C /usr/share/nginx/html/index.html C /var/cache/nginx D /var/cache/nginx/client_temp D /var/cache/nginx/fastcgi_temp D /var/cache/nginx/proxy_temp D /var/cache/nginx/scgi_temp D /var/cache/nginx/uwsgi_temp root@souyunku:~/mydocker#
咱们能够用下面的命令将容器保存为镜像:
$ docker commit \ --author "penglei <admin@souyunku.com>" \ --message "修改了默认网页" \ myweb \ nginx:v2 sha256:33b2e2aefccbaba54021c85ef7966c7d488abaa0677728e1b057c56a7734a4f0
其中 --author
是指定修改的做者,而 --message
则是记录本次修改的内容。这点和 git
版本控制类似,不过这里这些信息能够省略留空。
咱们能够在 docker image ls
中看到这个新定制的镜像:
$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE nginx v2 33b2e2aefccb About a minute ago 108MB nginx latest 3f8a4339aadd 3 days ago 108MB hello-world latest f2a91732366c 5 weeks ago 1.85kB
$ docker history nginx:v2 IMAGE CREATED CREATED BY SIZE COMMENT 33b2e2aefccb 2 minutes ago nginx -g daemon off; 325B 修改了默认网页 3f8a4339aadd 3 days ago /bin/sh -c #(nop) CMD ["nginx" "-g" "daemon… 0B <missing> 3 days ago /bin/sh -c #(nop) STOPSIGNAL [SIGTERM] 0B <missing> 3 days ago /bin/sh -c #(nop) EXPOSE 80/tcp 0B <missing> 3 days ago /bin/sh -c ln -sf /dev/stdout /var/log/nginx… 22B <missing> 3 days ago /bin/sh -c set -x && apt-get update && apt… 53.2MB <missing> 3 days ago /bin/sh -c #(nop) ENV NJS_VERSION=1.13.8.0.… 0B <missing> 3 days ago /bin/sh -c #(nop) ENV NGINX_VERSION=1.13.8-… 0B <missing> 2 weeks ago /bin/sh -c #(nop) LABEL maintainer=NGINX Do… 0B <missing> 2 weeks ago /bin/sh -c #(nop) CMD ["bash"] 0B <missing> 2 weeks ago /bin/sh -c #(nop) ADD file:f30a8b5b7cdc9ba33… 55.3MB
新的镜像定制好后,咱们能够来运行这个镜像。
$ docker run --name web2 -d -p 81:80 nginx:v2 ed8c54aeb3c540981b892c0cdfbf9330114ecc935149190e073f49295f2ae147
直接访问:http://localhost:81;若是使用的是 Docker Toolbox,或者是在虚拟机、云服务器上安装的 Docker,则须要将 localhost 换为虚拟机地址或者实际云服务器地址。
从刚才的 docker commit
的学习中,咱们能够了解到,镜像的定制实际上就是定制每一层所添加的配置、文件。若是咱们能够把每一层修改、安装、构建、操做的命令都写入一个脚本,用这个脚原本构建、定制镜像,那么以前说起的没法重复的问题、镜像构建透明性的问题、体积的问题就都会解决。这个脚本就是 Dockerfile
。
Dockerfile
是一个文本文件,其内包含了一条条的指令(Instruction
),每一条指令构建一层,所以每一条指令的内容,就是描述该层应当如何构建。
还以以前定制 nginx
镜像为例,此次咱们使用 Dockerfile
来定制。
在一个空白目录中,创建一个文本文件,并命名为 Dockerfile
:
$ mkdir mynginx $ cd mynginx $ touch Dockerfile
其内容为:
FROM nginx RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
这个 Dockerfile
很简单,一共就两行。涉及到了两条指令,FROM
和 RUN
。
所谓定制镜像,那必定是以一个镜像为基础,在其上进行定制。就像咱们以前运行了一个 nginx
镜像的容器,再进行修改同样,基础镜像是必须指定的。而 FROM 就是指定基础镜像,所以一个 Dockerfile
中 FROM
是必备的指令,而且必须是第一条指令。
在 Docker Store
上有很是多的高质量的官方镜像,有能够直接拿来使用的服务类的镜像,如 nginx
、redis
、mongo
、mysql
、httpd
、php
、tomcat
等;也有一些方便开发、构建、运行各类语言应用的镜像,如 node
、openjdk
、python
、ruby
、golang
等。能够在其中寻找一个最符合咱们最终目标的镜像为基础镜像进行定制。
若是没有找到对应服务的镜像,官方镜像中还提供了一些更为基础的操做系统镜像,如 ubuntu
、debian
、centos
、fedora
、alpine
等,这些操做系统的软件库为咱们提供了更广阔的扩展空间。
除了选择现有镜像为基础镜像外,Docker
还存在一个特殊的镜像,名为 scratch
。这个镜像是虚拟的概念,并不实际存在,它表示一个空白的镜像。
FROM scratch ...
若是你以 scratch
为基础镜像的话,意味着你不以任何镜像为基础,接下来所写的指令将做为镜像第一层开始存在。
不以任何系统为基础,直接将可执行文件复制进镜像的作法并不罕见,好比 swarm
、coreos/etcd
。对于 Linux
下静态编译的程序来讲,并不须要有操做系统提供运行时支持,所需的一切库都已经在可执行文件里了,所以直接 FROM
scratch
会让镜像体积更加小巧。使用 Go
语言 开发的应用不少会使用这种方式来制做镜像,这也是为何有人认为 Go 是特别适合容器微服务架构的语言的缘由之一。
RUN
指令是用来执行命令行命令的。因为命令行的强大能力,RUN
指令在定制镜像时是最经常使用的指令之一。其格式有两种:
shell
格式:RUN
<命令>,就像直接在命令行中输入的命令同样。刚才写的 Dockerfile
中的 RUN
指令就是这种格式。RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
既然 RUN
就像 Shell
脚本同样能够执行命令,那么咱们是否就能够像 Shell
脚本同样把每一个命令对应一个 RUN
呢?好比这样:
FROM debian:jessie RUN apt-get update RUN apt-get install -y gcc libc6-dev make RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz" RUN mkdir -p /usr/src/redis RUN tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 RUN make -C /usr/src/redis RUN make -C /usr/src/redis install
以前说过,Dockerfile
中每个指令都会创建一层,RUN
也不例外。每个 RUN
的行为,就和刚才咱们手工创建镜像的过程同样:新创建一层,在其上执行这些命令,执行结束后,commit 这一层的修改,构成新的镜像。
而上面的这种写法,建立了 7 层镜像。这是彻底没有意义的,并且不少运行时不须要的东西,都被装进了镜像里,好比编译环境、更新的软件包等等。结果就是产生很是臃肿、很是多层的镜像,不只仅增长了构建部署的时间,也很容易出错。 这是不少初学 Docker 的人常犯的一个错误。
Union FS
是有最大层数限制的,好比 AUFS
,曾经是最大不得超过 42 层,如今是不得超过 127 层。
上面的 Dockerfile
正确的写法应该是这样:
FROM debian:jessie RUN buildDeps='gcc libc6-dev make' \ && apt-get update \ && apt-get install -y $buildDeps \ && wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz" \ && mkdir -p /usr/src/redis \ && tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \ && make -C /usr/src/redis \ && make -C /usr/src/redis install \ && rm -rf /var/lib/apt/lists/* \ && rm redis.tar.gz \ && rm -r /usr/src/redis \ && apt-get purge -y --auto-remove $buildDeps
首先,以前全部的命令只有一个目的,就是编译、安装 redis
可执行文件。所以没有必要创建不少层,这只是一层的事情。所以,这里没有使用不少个 RUN
对一一对应不一样的命令,而是仅仅使用一个 RUN
指令,并使用 && 将各个所需命令串联起来。将以前的 7 层,简化为了 1 层。在撰写 Dockerfile
的时候,要常常提醒本身,这并非在写 Shell
脚本,而是在定义每一层该如何构建。
而且,这里为了格式化还进行了换行。Dockerfile
支持 Shell
类的行尾添加 的命令换行方式,以及行首 # 进行注释的格式。良好的格式,好比换行、缩进、注释等,会让维护、排障更为容易,这是一个比较好的习惯。
此外,还能够看到这一组命令的最后添加了清理工做的命令,删除了为了编译构建所须要的软件,清理了全部下载、展开的文件,而且还清理了 apt
缓存文件。这是很重要的一步,咱们以前说过,镜像是多层存储,每一层的东西并不会在下一层被删除,会一直跟随着镜像。所以镜像构建时,必定要确保每一层只添加真正须要添加的东西,任何无关的东西都应该清理掉。
不少人初学 Docker
制做出了很臃肿的镜像的缘由之一,就是忘记了每一层构建的最后必定要清理掉无关文件。
好了,让咱们再回到以前定制的 nginx
镜像的 Dockerfile
来。如今咱们明白了这个 Dockerfile
的内容,那么让咱们来构建这个镜像吧。
在 Dockerfile
文件所在目录执行:
$ docker build -t nginx:v3 . Sending build context to Docker daemon 2.048kB Step 1/2 : FROM nginx ---> 3f8a4339aadd Step 2/2 : RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html ---> Running in 5cdac6d29a52 Removing intermediate container 5cdac6d29a52 ---> 56a1b67b2533 Successfully built 56a1b67b2533 Successfully tagged nginx:v3
从命令的输出结果中,咱们能够清晰的看到镜像的构建过程。在 Step 2
中,如同咱们以前所说的那样,RUN
指令启动了一个容器 5cdac6d29a52
,执行了所要求的命令,并最后提交了这一层 56a1b67b2533
,随后删除了所用到的这个容器 5cdac6d29a52
这里咱们使用了 docker build
命令进行镜像构建。其格式为:
$ docker build [选项] <上下文路径/URL/->
镜像构建上下文(Context)若是注意,会看到 docker build
命令最后有一个 .
。.
表示当前目录
Git repo
进行构建或许你已经注意到了,docker build
还支持从 URL
构建,好比能够直接从 Git repo
中构建:
感谢:漠然提供 Git dockerfile repo
$ docker build https://github.com/mritd/dockerfile.git#:alpine-glibc
... Executing ca-certificates-20171114-r0.post-deinstall Executing busybox-1.27.2-r6.trigger OK: 11 MiB in 14 packages Removing intermediate container baf41e622959 ---> aded3329be1b Step 3/3 : ENV LANG=C.UTF-8 ---> Running in 8c34e0f4d25b Removing intermediate container 8c34e0f4d25b ---> c493a5aa5eb7 Successfully built c493a5aa5eb7
这行命令指定了构建所需的 Git repo
,而且指定默认的 master
分支,构建目录为 /alpine-glibc/,而后 Docker
就会本身去 git clone
这个项目、切换到指定分支、并进入到指定目录后开始构建。
$ docker build http://server/context.tar.gz
若是所给出的 URL 不是个 Git repo
,而是个 tar 压缩包,那么 Docker 引擎会下载这个包,并自动解压缩,以其做为上下文,开始构建。
Dockerfile
进行构建$ docker build - < Dockerfile
或
$ cat Dockerfile | docker build -
若是标准输入传入的是文本文件,则将其视为 Dockerfile
,并开始构建。这种形式因为直接从标准输入中读取 Dockerfile
的内容,它没有上下文,所以不能够像其余方法那样能够将本地文件 COPY 进镜像之类的事情。
$ docker build - < context.tar.gz
若是发现标准输入的文件格式是 gzip、bzip2
以及 xz
的话,将会使其为上下文压缩包,直接将其展开,将里面视为上下文,并开始构建。
参考:Docker — 从入门到实践
https://www.gitbook.com/download/pdf/book/yeasy/docker_practice
参考:Docker 官网 Get Docker CE for Ubuntu