Docker学习笔记.初识Docker

Posted qq_51102350

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Docker学习笔记.初识Docker相关的知识,希望对你有一定的参考价值。

Docker

一,惊鸿一瞥

容器技术:让多个独立的用户空间运行在同一台宿主机上。
容器只能运行于底层宿主机相同或相似的操作系统。
例如:

可以在Ubuntu中运行RedHat Enterprise Linux,却无法运行Microsoft Windows

容器常用于多租户服务器部署、轻量级沙盒和安全要求不高的隔离环境中。

Docker:能开发的应用程序自动部署到容器的开源引擎。
作用:

  • Docker上手很快,只需不到一秒的时间启动,且性能很高
  • 职责分离:使用Docker,开发人员只需关心应用程序,运维人员只需关心如何管理容器
  • 快速、高效的开发生命周期
  • 鼓励面向服务架构

组件:

  • Docker引擎(客户端和服务器)
    Docker是一个客户端/服务器(C/S)架构的程序

  • Docker镜像
    镜像是基于联合(Union)文件系统的一种层式架构,由一系列指令构成
    如:添加一个文件、执行一个命令或打开一个端口

  • Registry
    用于保存用户构建的镜像。

  • Docker容器
    镜像是Docker生命周期的构建和打包阶段,容器是启动或执行阶段

总而言之,可以把Docker理解为一个隔离的环境。

二,Docker入门

1,运行容器

$ sudo docker run -t -i ubuntu /bin/bash
  • 首先,执行docker run命令
  • 指定 -i 和 -t 两个命令行参数
  • -i:保证容器STDIN是开启的
  • -t:让Docker为要创建的容器分配一伪tty终端
  • 通过-i和-t,新建的容器才能提供一个最基本的交互式shell
  • ubuntu指定容器的镜像为ubuntu镜像
  • 最后告诉Docker在新容器中运行的命令,/bin/bash是示例中要执行的命令,能启动一个Bash shell

结果:
最末行的root@6013408ebadd:/#就是该容器的shell
注:

  • shell:是用户和linux间的接口程序,在terminal内输入的每个命令都由shell解释后传给linux
  • bash shell是一种shell

2,简单使用

//检查容器主机名
$ hostname

//检查容器/etc/hosts文件
$ cat /etc/hosts

//检查容器进程
$ ps -aux

//安装软件包,此处安装了Vim软件
$ apt-get update && apt-get install vim

//退出
$ exit

//列出所有Docker容器(该命令在ubuntu宿主机的terminal中给出
$ sudo docker ps -a

//用--name标志创立一个指定名称的容器
$ sudo docker run --name my_first_docker -i -t ubuntu /bin/bash

//重新启动已经停止的容器
$ sudo docker start 容器名/容器Id

//重新附着到容器上
$ sudo docker attach 容器名/容器Id

3,守护式容器

上面通过-t -i 两个命令行参数实现了交互式运行的容器(interactive container)
还可以使用 -d 参数来创建一个守护式容器(daemonized container)
有以下特点:
无交互式会话
适合运行应用程序和服务
可以长期运行

$ sudo docker run --name daemon_dave -d ubuntu /bin/sh -c "while true; do echo hello world; sleep 1; done"

自-c后面的部分使用了一个while循环,在容器运行期间会一直打印hello world

//获取容器日志
$ sudo docker logs 容器名/id

//跟踪守护式容器的日志没,利用参数-f,使用crtl+c退出
$ sudo docker logs -f 容器名/id 

//使用-t参数找到每条日志的时间
$ sudo docker logs -ft 容器名/id

//查看容器内进程
$ sudo docker top 容器名/id

//查看docker统计信息
$ sudo docker stats 一系列守护式容器名,以空格键分隔

//停止守护式容器
$ sudo docker stop 容器名/容器id

//显示最后x个容器,无论容器是运行还是停止
$ sudo docker ps -n x

docker日志驱动:
docker日志驱动

4,在容器内部运行进程

容器内运行的进程分为后台任务和交互式任务

使用docker exec在容器创建新的进程

示例:

$ sudo docker exec -d daemon_dave touch /etc/new_config_file
  • -d标志表示运行的是后台进程
  • -d之后首先指定容器名字
  • 之后的touch会在容器内创建一个空文件,名为/etc/new_config_file

可以使用参数 -t -i创建交互式进程

//在指定容器中创建一个新的bash会话
$ sudo docker exec -t -i 容器名 /bin/bash

5,自动重启容器和删除容器

自动重启容器:若因某种错误导致容器停止,则应重启容器
–restart 标志会在检查容器退出代码,并依次决定是否重启容器

$ sudo docker run --restart=可选标志 --name 容器名 -d ubuntu /bin/sh -c "while true; do echo hello world; sleep 1; done"

可选标志:

  • always:无论退出代码是啥,都会重启
  • on-failure:退出代码非0,则重启
  • on-failure:count:count指定最大重启次数

删除容器:

$ sudo docker rm 容器名/id

//删除运行中的容器
$ sudo docker rm -f 容器名/id

//删除所有容器,首先停止容器运行,然后删除
$ sudo docker stop $(sudo docker ps -a -q)
$ sudo docker rm $(sudo docker ps -a -q)

6,深入容器

暂时搁置

三,使用Docker镜像和仓库

1,基本镜像操作

镜像来源于仓库,仓库存在于Registry中
默认的Registry是Docker Hub

仓库:包括镜像/层以及关于镜像的元数据
每个仓库中可存储多个镜像
使用标签区分一个仓库下的不同镜像

//列出镜像
$ sudo docker images

//从仓库中拉取Ubuntu镜像
$ suodo docker pull ubuntu:标签

//查看指定镜像
$ sudo docker images 镜像名

docker
Docker Hub中有两种类型的仓库:
用户仓库(user repository):由用户创建
命名:用户名/仓库名

顶层仓库(top-level repository):由Docker内部管理
命名:仓库名

查找镜像:
示例:查找带有goland的镜像

2,用Dockerfile构建镜像

用Dockerfile的定义文件和docker build命令来构建镜像

Ⅰ,构建Dockerfile

首先,创建目录用来保存Dockerfile

//创建目录
$ mkdir 目录名
//移到该目录
$ cd 目录名 

//建立新文件
touch Dockerfile
//或
vim Dockerfile

然后,在新文件中编译

# Version 0.0.1
FROM 仓库名(:标签)
MAINTAINER hwc "hitwhhwc@163.com"
RUN ..
EXPOSE

每条指令(如FROM)必须为大写字母,后面跟随一个参数

  • FROM指令用于指定已存在的镜像
  • MAINTAINER用于指定镜像作者,以及他的电子邮件地址
  • RUN会运行指定指令
  • EXPOSE指令指定要使用的指定端口

最后,运行Dockerfile

$ cd 目录名
$ sudo docker build -t="仓库名/镜像名" .

//设置标签
$ sudo docker build -t="仓库名/镜像名:v1" .

//查看镜像如何构建
$ sudo docker history 镜像名/id

若没有指定任何标签,则会自动添加latest标签

Ⅱ,从新镜像启动容器

示例:

$ sudo docker run -d -p 80 --name 容器名称 仓库名称/镜像名称 \\nginx -g "daemon off;"
  • 指定了在容器中运行的命令:nginx -g "daemon off;",这将以前台的方式启动Nginx,作为Web服务器
  • -p标准控制Docker运行时应公开给外部(宿主机)的网络端口

Docker可通过两种方法来在宿主机上分配端口:

  • Docker可在宿主机上随机选择一个位于32768~61000间的一个较大的端口号来映射到容器的80端口上
  • 可以指定具体的端口号来映射

查看端口映射情况:

$ sudo docker ps -l

$ sudo docker port 容器id/名称 容器端口号

如:
使用-P参数来对外公开在Dockerfile中通过EXPOSE指令指定的所有端口:

$ sudo docker run -d -P --name 容器名 仓库名/镜像名 \\nginx -g "daemon off;"

使用curl连接到容器:

3,Dockerfile指令

Ⅰ,CMD

用于指定容器启动时要运行的命令
与之对比,RUN指定镜像被构建时要运行的命令

两者等效:

$ sudo docker run -i -t demo/test web /bin/true

CMD ["/bin/true"]

//可为CMD指定参数:
CMD ["/bin/bash","-l"]

注意:要运行的命令存放在一个数组结构中

docker run命令可覆盖CMD命令:
当用CMD指定容器启动时要运行的命令后:

#没有指定要运行的命令,将使用CMD指令中的命令
$ sudo docker run -i -t demo/test

#覆盖本地命令
$ sudo docker run -i -t demo/test 新命令

Ⅱ,ENTRYPOINT

与CMD的区别:
可以在docker run 中覆盖CMD的命令,而ENTRYPOINT的命令不容易在启动容器时被覆盖
docker run中的任何参数都会作为参数传递给ENTRYPOINT中指定的命令

看如下例子:
首先,设置ENTRYPOINT

ENTRYPOINT ["/usr/sbin/nginx"]

然后构建镜像

$ sudo docker build -t="demo/test" .

最后启动容器

$ sudo docker run -i -t demo/test -g "daemon off;"

这里指定了-g "daemon off;"的参数
这样,会构成命令:

/usr/sbin/nginx -g "daemon off;"

组合使用ENTRYPOINT和CMD:
如:

ENTRYPOINT ["/usr/sbin/nginx"]
CMD ["-h"]

此时,当在docker run命令中指定其它参数(如-g "daemon off;")时,会覆盖CMD中参数,否则,会运行默认的命令

Ⅲ,WORKDIR

用于从镜像创建一个新容器时,在容器内部设置一个工作目录
如:

WORKDIR /opt/webapp/db
RUN bundle install
WORKDIR /opt/webapp
ENTRYPOINT ["rackup"]

首先将工资目录切换为/opt/webapp/db后,运行bundle,然后又切换为/opt/webapp,设置ENTRYPOINT

可使用 -w 标志在运行时覆盖工作目录:

$ sudo docker run ti -w 指定目录 ubuntu pwd

Ⅳ,ENV

用于在镜像构建过程中设置环境变量

示例:

#Ddockerfile:
ENV RVM_PATH /home/rvm/

#为RUN指令设置前缀:
RUN gem install unicorn

#上述两语句等价于:
RUN RVM_PATH=/home/rvm/ gem install unicorn

#也可用于设置多个环境变量
ENV RVM_PATH=/home/rvm/ RVM_ARCHFLAGS="-arch i386"

#可在其他Dokcerfile指令中使用环境变量:
#WORKDIR指令的值会被设为/opt/app
ENV TARGET_DIR /opt/app
WORKDIR $TARGET_DIR

用ENV设置的环境变量会保存到任何该镜像创建的容器中

也可以使用docker run命令行-标志来传递环境变量,这些变量只会在运行时有效
例子:

$ sudo docker run -ti -e "WEB_PORT=8000" ubuntu env

Ⅴ,USER

指定该镜像会以是什么样的用户去运行

示例:

USER 用户名
USER UID
USER 用户名:组名
USER 用户名:GID
USER UID:组名
USER UID:GID

Ⅵ,VOLUME

向基于镜像创建的容器添加卷

  • 卷是持久化的目录
  • 可在容器中共享重用
  • 卷会一直存在直到没有任何容器使用它

示例:

#为任何基于此镜像创建的容器创建一个挂载点:/opt/project
VOLUME ["/opt/project"]

#指定多个卷
VOLUME ["/opt/project","/data"]

Ⅶ,ADD

用于将构建环境下的文件和目录复制到镜像中

示例

# 在安装一个应用程序时,需提供源文件位置和目的文件位置两个参数
# 这里将software.lic文件复制到后面的文件位置中
ADD software.lic /opt/application/software.lic

#也可以使用URL作为文件源
ADD https://www.jetbrains.com/go/download/download-thanks.html?platform=linux

ADD处理本地归档文件(tar archive)(包括gzip,bzip2,xz)时,能将文件解开(unpack)

#将归档文件解压到目的目录
ADD latest.tar.gz /var/www/wordpress/

若目的文件位置不存在,那么会创建该路径。

Ⅷ,COPY

COPY类似ADD
COPY只复制文件,而不会提取(extraction)和解压(decompression)
其语法与ADD类似

Ⅸ,LABEL

用于为Dokcer镜像添加元数据
形式:键对值

LABEL version="1.0"
LABEL location="WEI HAI" type="Domitpry" role="Web Server"

可以通过多个LABEL命令来添加,但还是建议通过一条LABEL命令来添加所有需要的元数据,因为不同的元数据指令会创建过多的镜像层

查看容器标签:

$ sudo docker inspect demo/test

Ⅹ,ARG

指定一个变量,在docker build时使用
使用变量:在docker build时传递–build-arg <variable>=<value>

#添加ARG指令
ARG build
#这里为参数设置了一个默认值
ARG webapp_user=user

#使用ARG指令
#build变量设置成了1234,webapp_user则会使用默认值
$ docker build --build-arg build=1234 -t demo/test

一些预定义ARG变量:

HTTP_PROXY
http_proxy
HTTPS_PROXY
https_proxy
FTP_PROXY
ftp_proxy
NO_PROXY
no_proxy

Ⅺ,ONBUILD

在Dockerfile中构建一个触发器
当一个镜像被其他镜像作为基础镜像时,该镜像的触发器会执行
其他指令都是为了帮自己订制镜像,而ONBUILD是为了帮他人订制自己

格式:ONBUILD <其他指令>

可用docker inspect命令查看镜像中的ONBUILD命令

$ sudo docker inspect 容器id,容器名

推送镜像:

$ sudo docker push 用户仓库名

4,删除镜像

$ sudo docker rmi 镜像名1, 镜像名2

#删除所有镜像
$ sudo docker rmi $(sudo docker images -a -q)

以上是关于Docker学习笔记.初识Docker的主要内容,如果未能解决你的问题,请参考以下文章

Docker学习笔记.初识Docker

Docker学习笔记.初识Docker

docker学习笔记2 -- 资源限制

docker 学习笔记

Docker学习笔记-简介

docker学习笔记——Dockerfile创建自定义镜像