Docker 使用教程
一些概念
Docker Registry
Docker 远程镜像仓库
- DockerHub
- DaoCloud / Aliyun
Docker Images
Docker Images
是用来创建 docker 容器的只读模版,其中包含了容器启动所需要的所有配置信息和运行程序,一次构建之后可以多次复用。
从结构上来讲,Docker Image
是分层次的,如图所示:
这样就自然出现了父镜像和基础镜像的概念,在图中,每一个上层镜像都是依赖于下一层的镜像,所以下层镜像可称为上层镜像的父镜像,而最底层的镜像是没有父镜像的,可称其为基础镜像(Base Image)。
实际场景下,一般我们自己创建的镜像都会依赖于某个 Linux
操作系统的镜像,例如 ubuntu
,大多数情况下,我们可称其为基础镜像,但是我们也可以查看 ubuntu
镜像的 Dockerfile
会发现,它也是依赖于一个叫 scratch
的镜像,scratch
是 docker
的一个空镜像,里面只有 docker
加入的一些元数据,如果我们想要追求自己的镜像尽可能的轻量,也可以将 scratch
镜像作为我们的基础镜像来构建。
Dockerfile
Dockerfile
是用来说明如何自动构建 docker image
的指令集文件,在 Dockerfile
中编写好指令集之后,我们就可以通过 docker build
命令构建镜像,Dockerfile
文件中命令的顺序就是构建过程中执行的顺序。
以下为几个常用的指令:
1. FROM:依赖镜像
所有 Dockerfile
都必须以 FROM
命令开始,表示其依赖的镜像。
1 | FROM image_name |
2. MAINTAINER:镜像作者信息
1 | MAINTAINER author <author_email> |
3. RUN:在shell或者exec的环境下执行的命令
1 | RUN <command> |
4. ADD:将主机文件复制到容器中
1 | ADD /path/to/sourcefile/in/host /path/to/targetfile/in/container |
5. CMD:指定容器启动默认执行的命令
1 | CMD ["executable","param1","param2"] |
6. EXPOSE:指定容器在运行时监听的端口
1 | EXPOSE <port> |
7. WORKDIR:指定RUN
、CMD
与 ENTRYPOINT
命令的工作目录
1 | WORKDIR /path/to/workdir/in/container |
8. VOLUME:授权访问从容器内到主机上的目录
1 | VOLUME ["/data"] |
关于 Dockerfile
编写有以下几点需要注意:
- 尽量不要省略
MAINTAINER
信息。 EXPOSE
的端口不使用公有端口。CMD
与ENTRYPOINT
命令使用数组语法。
另外,在国内使用 docker
(以 ubuntu 为例), Dockerfile
第一个执行的命令最好为(具体原因你猜):
1 | RUN sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list \ |
Docker Container
Docker Container
中包含了我们的应用代码和代码执行的环境,是用来打包分发代码的单元。
构建镜像
首先要编写 Dockerfile
,在文件中写入构建镜像需要的指令集,然后执行下面命令:
1 | docker build {image_name} {/path/to/Dockerfile} |
例如,我们构建一个 mysql
的镜像,先编写 Dockerfile
1 | FROM ubuntu:14.04 |
执行
1 | docker build -t mysql ./ |
构建工具将先在本地查找 ubuntu:14.04
的镜像,如果有,则直接依赖使用,如果没有,将去远程的仓库中下载官方构建的 ubuntu:14.04
的镜像,当然因为一些不可描述的原因,这个下载过程成功率不大,而且非常耗时,所以我们可以做如下优化:
1 | docker pull daocloud.io/library/ubuntu:wily-20160706 |
然后将 Dockerfile
中 FROM
命令修改为:
1 | # 我注册了daocloud 账号,就使用 daocloud 的镜像,也可以选择使用阿里云的镜像。 |
这样,就节省了很多的时间。
总之,在安装环境的过程中,因为某个伟大的防火墙工程,我们需要的大部分资源都没法顺利的获取到,解决办法就是将下载的源换成国内某些厂商提供的镜像源。(推荐阿里云,毕竟有钱,稳定。)
经过一段时间的自动构建,便可生成一个可用的 mysql
镜像,使用 docker images
命令查看构建好的镜像列表,输出:
1 | REPOSITORY TAG IMAGE ID CREATED SIZE |
删除一个镜像,使用下面命令:
1 | # -f 表示强制删除,慎重使用 |
创建容器
有了基础的镜像模板之后,就可以创建容器来执行应用代码,具体用到 run
命令:
1 | docker run [OPTIONS] IMAGE [COMMAND] [ARG...] |
例如我们要创建一个运行 mysql 的容器,可以执行
1 | docker run -d --name db1 -v `pwd`:/data:rw -p 8001:3306 mysql |
这条命令将创建后台执行的 mysql 容器,里面运行一个 mysql 服务器,可以使用 docker ps
命令查看启动的容器。
- -d 参数表示后台守护进程运行容器。
- –name 参数表示容器的名称,可随意取。
- -v 表示主机和容器共享文件的映射,容器的目录就是 Dockerfile 中用 VOLUME 命令定义的目录。
- -p 表器主机和容器端口映射,容器的端口就是 Dockerfile 中用 EXPOSE 命令绑定的端口。
关于创建容器的时候的坑:
一般来说,我们会在
Dockerfile
中的最后用 CMD 命令定义容器启动之后执行的命令,但是如果我们定义的命令执行报错或者命令没有创建一个守护进程的话,docker ps
之后是看不到容器在运行的,此时可以使用docker l ogs
命令查看容器启动的日志,进行排错。
当然,我们也可以在 run 的时候定义容器启动的命令,例如下面命令将启动一个 ubuntu 的容器,并执行 /bin/bash
程序,进入 ubuntu 的 terminal:
1 | docker run -it ubuntu:14.04 /bin/bash |
此命令成功的标志就是你会发现命令行变成了类似:
1 | root@d71ff8587917:/# |
说明现在已经进入了 ubuntu
的容器中,可以直接在此命令行中操作 ubuntu
,或者输入 exit
回车之后即可退出,退出之后再 docker ps
会发现容器也不再运行了。
一些常用命令:
docker ps -a
命令可以列出所有的容器,包括已经终止运行的。docker rm container_name/container_id
可以删除某个容器。docker start container_name/container_id
启动某个容器。docker stop container_name/container_id
终止某个容器。docker exec -it contaner_name /bin/bash
在容器中执行/bin/bash
,执行该命令之后将可以以交互命令行的方式操作容器,另外/bin/bash
可以替换成任意可执行命令。
Docker compose
docker-compose
是用来创建和管理多容器应用的工具,使用 docker-compose
只需三步:
- 编写应用运行环境的
Dockerfile
,即 image。 - 编写
docker-compose.yml
,在services
块下指定容器相关参数以及与其它容器的依赖关系。 - 执行
docker-compose up
,运行应用。
一个简单的 docker-compose.yml
如下:
1 | version: '2' # compose 版本,当前为 2 |