安装
首先在Docker的官方网站下下载相应的版本,由于默认宿主机均为Mac,所以直接下载Mac版本,其中Docker-Compose(Docker官方的Orchestration项目之一,主要负责快速在集群中部署应用)已经默认安装在Mac版本的Docker中,所以无需再额外下载。
基本使用(Dockerfile)
docker build
假设基本已经知道了Docker的基本知识,直接进入主体。
首先,单个镜像是基于Dockerfile来生成的,Dockerfile可以认为是描述这个镜像的脚本,在其上下文环境中,使用docker build就可以运行Dockerfile生成镜像。比如在文件test中,Dockerfile也是在这个文件中,运行build
docker build .
其中 (.) 代表着就是dockerfile所在的上下文环境。 (.) 不可缺少。 可以将上下文理解为传入docker build中的参数,不一定是(.) 。也可以是路径,甚至是URL。基本语法如下
#选项可以在官方文档中查阅到
docker build [选项] <上下文路径/URL/->
其他build用法如下,还可以直接用Git repository来构建
$ docker build https://github.com/twang2218/gitlab-ce-zh.git#:8.14 docker build https://github.com/twang2218/gitlab-ce-zh.git\#:8.14 Sending build context to Docker daemon 2.048 kB
Step 1 : FROM gitlab/gitlab-ce:8.14.0-ce.0
8.14.0-ce.0: Pulling from gitlab/gitlab-ce
aed15891ba52: Already exists
773ae8583d14: Already exists
...
这行命令指定了构建所需的 Git repo
,并且指定默认的 master
分支,构建目录为 /8.14/
, 然后 Docker
就会自己去 git clone
这个项目、切换到指定分支、并进入到指定目录后开始构建。
具体Dockerfile中命令如下
# 这行代表着我们制作的镜像是基于官方的nodejs最新版本的,由FROM开头,冒号之后代表的是版本号,如果不填写,会默认为最新版(latest)
FROM node:latest
# 这行定义的是维护人和维护人邮箱,由MAINTAINER开头
MAINTAINER lossp “richard.xxmxx@gmail.com”
# 第一行是定义运行创造/home/Service命令
#第二行是定义工作目录为/home/Servive
RUN mkdir -p /home/Service
WORKDIR /home/Service
#第一行是从上下文环境中的/home/Service 复制文件,copy命令的源路径都是相对路径
#第二行是执行npm install 命令
COPY . /home/Service
RUN npm install
# 将端口3000暴露出来,可以供外界访问,或者映射到宿主机的端口上去
EXPOSE 3000
CMD [ "npm", "start" ]
FROM
FROM - 其中FROM命令是必须的,但是不一定需要基于某一个镜像,可以从0开始构建,此时就需要使用scratch,scratch代表着一个空白的镜像。此时基本命令就是
FROM scratch
MAINTAINER
MAINTAINER - 就是将维护人信息添加到脚本文件中,不一定需要,可有可无。
RUN
RUN - RUN命令是用来执行基本命令的,基本格式有两种,第一种是Shell格式,RUN <命令>;
RUN npm install
第二种是exec格式,如下
RUN ["可执行文件", "参数1", "参数2"]
第二种更像是函数中的调用格式。
由于Dockerfile每一个命令都会建立一层,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
类似上述例子,一共构建了7层镜像,这是完全没有意义的,而且很多运行时不需要的东西,都被装进了镜像里,比如编译环境、更新的软件包等等。结果就是产生非常臃肿、非常 多层的镜像,不仅仅增加了构建部署的时间,也很容易出错。
正确的编写应该如下例子
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的RUN命令更具有可读性。
此外,命令的最后一行还有一个 --auto-remove
命令,这个为清理工作的命令,删除了编译所需要的软件,清理下载以及展开的文件,并且还清理了apt
缓存文件。由于镜像是一层一层构建的,每一层的多余东西并不会在下一层中被删除掉,到后面,镜像会越来越大。因此清理这些没有用处的东西很有必要。
COPY
COPY - copy命令的源路径都是相对路径,比如
COPY ./package.json /app/
这并不是要复制执行 docker build
命令所在的目录下的 package.json
,也不是复制 Dockerfile
所在目录下的 package.json
,而是复制 上下文(context) 目录下的 package.json
。
一般来说,应该会将 Dockerfile
置于一个空目录下,或者项目根目录下。如果该目录下没 有所需文件,那么应该把所需文件复制一份过来。如果目录下有些东西确实不希望构建时传 给 Docker
引擎,那么可以用.gitignore
一样的语法写一个.dockerignore
,该文件是用于 剔除不需要作为上下文传递给 Docker
引擎的。
这只是默认行为,实际上 Dockerfile
的文件名并不要求必须为 Dockerfile
,而且并不要求 必须位于上下文目录中,比如可以用 -f ../Dockerfile.php
参数指定某个文件作为Dockerfile
CMD
CMD - CMD容器启动命令。CMD命令和RUN命令相似,也是两种格式,分别为shell命令格式和exec命令格式。
Docker 不是虚拟机,容器就是进程。既然是进程,那么在启 动容器的时候,需要指定所运行的程序及参数。CMD 指令就是用于指定默认的容器主进程的 启动命令的。
在exec命令格式上,一般会被解析成json数组格式,需要用双引号,不能使用单引号!!!
Docker-compose
Compose的定位是定义和运行多个 Docker 容器的应用(Defining and running multi- container Docker applications)。
由于Dockerfile对于仅仅是单个镜像而言,而在正常的开发环境中,我们需要多个容器协调合作来完成某一个工作,比如一个web项目,除了web本身以外,还需要均衡负载,数据库等。
compose恰好能满足这样的要求,compose允许用户通过一个docker-compose.yml模版文件来定义互相关联的容器,来组成为一个项目。
compose中有如下两个重要的概念
---服务(Service): 一个应用的容器,实际上可以包括若干运行相同镜像的容器实例
---项目(project): 由一组关联的应用容器组成的一个完整业务单元,在 docker- compose.yml 文件中定义。
compose默认的管理对象是项目,通过子命令对项目中的一组容器的生命周期进行便携管理。
下面是具体例子说明
Dockerfile
version: "2.0"
services:
ubuntu:
image: ubuntu:16.04
restart: always
ports:
- "1234:1234"
nodejs:
image: mynodeapp
restart: always
ports:
- "3000:3000"
nginx:
image: nginx
restart: always
ports:
- "8080:80"
redis:
image: redis:latest
restart: always
ports:
- "6379:6379"
mysql:
image: mysql:5.7
restart: always
ports:
- "27017:27017"
由于其中mysql与redis没有进行详细配置,因此并不能完全工作,只是作为展示用,其中image代表着基本哪些基本镜像。可以将image
替换为build
,build
相关镜像,然后基于这个镜像。每一个容器必须定一个image或者build。
以下为命令上诉例子命令解释,更多命令参照官方文档
---ports: 暴露端口信息,使用宿主端口:容器端口 (HOST:CONTAINER)
格式,或者仅仅指定容器的端口(宿主将会随机 选择端口)都可以
(当使用 HOST:CONTAINER
格式来映射端口时,如果你使用的容器端口小于 60 并且没放 到引号里,可能会得到错误结果,因为 YAML 会自动解析 xx:yy 这种数字格式为 60 进制。 为避免出现这种问题,建议数字串都采用引号包括起来的字符串格式)
---volumes: 对于此命令,在上述例子中没有,但是对于容器之间共享数据是不可获取的,数据卷所挂载路径设置。可以设置宿主机路径 ( HOST:CONTAINER )
或加上访问模式 ( HOST:CONTAINER:ro )
。volumes 关键字相当于 docker run
的-v
参数,用于配置数据卷。这里与之前的做法一 样,将 app 目录通过绑定挂载的方式挂载到容器,以便让我们能够从主机修
运行docker-compose
项目的时候使用如下命令
docker-compose up
Docker-compose的大致工作流程如下
---up: 启动所有在 Compose 文件中定义的容器,并且把它们的日志信息汇集一起。通常会使 用 -d 参数使 Compose 在后台运行
---build: 重新建造由 Dockerfile 构建的镜像。除非镜像不存在,否则 up 命令不会执行构建的动作,因此需要更新镜像时便使用这个命令
---ps: 获取由 Compose 管理的容器的状态信息
---run: 启动一个容器,并运行一个一次性的命令。被连接的容器会同时启动,除非用了 --no- deps 参数
---logs: 汇集由 Compose 管理的容器的日志,并以彩色输出
---stop: 停止容器,但不会删除它们
结语
首先如果要定制自己的镜像,首先流程想清楚--->Dockerfile脚本编写--->在iterm中运行docker build -t <name> .
--->运行docker run -d -p 3000:3000 <name>
---->打开浏览器输入localhost:3000即可
上述仅仅是示例流程,对于单个image而言。
如果是采用docker-compose方式
相关本地镜像的构建,采用单个dockerfile然后build方式---->相关需求梳理,比如redis,mysql等---->编写docker-compose脚本,确定各个容器依赖关系---->docker-compose up运行----->浏览器打开相应端口
网友评论