一、docker简介
1. docker诞生
docker 是 dotcloud 公司开源的一款产品,dotcloud 是2010年新成立的一家公司,主要基于 PAAS(Platfrom as a Service)平台为开发者提供服务。2013年10月dotcloud 公司改名为docker 股份有限公司。
2. docker 相关解释
Linux Container 是一种内核虚拟化技术,可以提供轻量级的虚拟化,以便隔离进程和资源。
docker 是 PAAS 提供商 dotcloud 开源的一个基于 LXC 的高级容器引擎,源代码托管在GitHub上,基于go 语言并遵从 Apache2.0 协议开源。即docker是基于go语言并遵从apache2.0协议的一个基于LXC 的高级容器引擎。
docker 设想是交付运行环境如同海运,OS 如同一个货轮,每一个在OS 基础上的软件如同一个集装箱,用户可以通过标准化手段自由组装运行环境,同时集装箱的内容可以由用户自定义,也可以由专业人员制造。
3. docker 与传统虚拟化对比
4. docker 的构成
docker 仓库:https://hub.docker.com/
docker 自身组件
docker client:docker 客户端
docker server:docker daemon 的主要组成部分,接受用户通过docker client 发出的请求,并按照相应的路由规则实现路由分发
docker 镜像:docker 镜像运行之后变成容器(docker run)
二、docker 安装
1. docker 的安装方式
1.1 shell 脚本安装
# yum update # curl -sSL https://get.docker.com/ |sh # systemctl start docker # systemctl enable docker # docker run hello-world Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world 1b930d010525: Pull complete Digest: sha256:d1668a9a1f5b42ed3f46b70b9cb7c88fd8bdc8a2d73509bb0041cf436018f 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 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://hub.docker.com/ For more examples and ideas, visit: https://docs.docker.com/get-started/
1.2 yum 安装
# yum update # cd /etc/yum.repos.d/ # vim docker.repo [dockerrepo] name=Docker Repository baseurl=https://yum.dockerproject.org/repo/main/centos/7 enabled=1 gpgcheck=1 gpgkey=https://yum.dockerproject.org/gpg # yum -y install docker # systemctl start docker # systemctl enable docker # docker run hello-world
1.3 rpm 包安装
下载地址:https://download.docker.com/linux/centos/7/x86_64/stable/Packages/
2. docker 镜像加速配置
# cp /lib/systemd/system/docker.service /etc/systemd/system/ # cd /etc/systemd/system/ # chmod a+x docker.service # vim docker.service ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd .sock --registry-mirror=https://ehkb3m8v.mirror.aliyuncs.com # systemctl daemon-reload # systemctl restart docker
https://ehkb3m8v.mirror.aliyuncs.com 获取方法
a. 进入阿里云镜像加速界面
https://cr.console.aliyun.com/#/accelerator
三、docker 容器管理
1. docker 基础概念
docker 三个重要概念:仓库(Repository)、镜像(image)、容器(Container)
docker -run --name MyWorkPress --link db:mysql -p 81:80 -d wordpress
docker 指令的基本用法:
docker + 命令关键字(COMMON)+ 一系列参数
2. docker 命令
docker run:创建一个新的容器并运行一个命令 docker run [options] image [command] [arg...] options常用说明: ·-d 后台运行容器。并返回容器ID ·-i 以交互模式运行容器,通常与 -t 一起使用 ·-P(大) 随机端口映射,容器内部端口随机映射到主机的高端口 ·-p 指定端口映射,格式为:主机端口:容器端口 ·-t 为容器重新分配一个伪输入终端,通常与 -i 一起使用 ·--name="nginx1" 为容器指定一个名称 ·--dns 8.8.8.8 指定容器使用的DNS服务器,默认与宿主机一致 ·--dns-search example.com 指定容器DNS搜索域名,默认与宿主机一致 ·-h "nginx" 指定容器的hostname ·-e username="nginx" 设置环境变量 ·--env-file=[] 从指定文件读入环境变量 ·-m 设置容器使用内存最大值 ·--net="bridge" 指定容器的网络连接类型,支持bridge/host/none/container 四种类型 ·--link=[] 添加链接到另一个容器 ·--expose=[] 开放一个端口或一组端口 ·--volume ,-v 绑定一个卷
docker start 启动一个或多个已经被停止的容器
docker stop 停止一个容器
docker restart 重启容器
docker kill 杀掉一个运行中的容器-s 向容器发送一个信号 杀掉正在运行中的容器nginx # docker kill -s KIll nginx
docker rm 删除一个或多个容器 -f 强制删除 # docker rm -f nginx # docker rm $( docker ps -a -q )
docker exec 在运行的容器中执行命令
# docker exec -it nginx /bin/bash
docker ps 列出容器 -a 显示所有容器,包括未运行的 -f 根据条件过滤显示的内容 --format 指定返回值的模板文件 --no-trunc 不截断缓存 -q 静默模式。只显示容器编号 -s 显示总的文件大小
docker inspect 获取容器/镜像的元数据 -f 指定返回值的模板文件 -s 显示总的文件大小 --type 为指定类型返回JSON
docker logs 获取容器日志 -f 跟踪日志输出 --since 显示某个开始时间的所有日志 -t 显示时间戳 --tail 仅列出最新N条容器日志
docker commit 从容器创建一个新的镜像 -a 提交的镜像作者 -c 使用Dockerfile指令来创建镜像 -m 提交时的说明文字 -p 在commit时,将容器停止
docker cp 用于容器与主机之间的数据拷贝 # docker cp f2c8da58d4da:/etc/nginx/conf.d /tmp # docker cp /usr/local/nginx/html f2c8da58d4da:/usr/share/nginx
docker diff 查看容器里文件结构的更改
docker login 登陆到一个Docker镜像仓库,如果未指定镜像仓库地址,默认为官方仓库 Docker Hub docker logout 登出一个Docker镜像仓库,如果未指定镜像仓库地址,默认为官方仓库 Docker Hub # docker login -u username -p password
docker pull 从镜像仓库中下载或更新指定的镜像
docker push 将本地镜像上传到镜像仓库,要先登录到镜像仓库
docker search 从镜像仓库查找镜像
docker images 列出本地镜像 -a 列出本地所有的镜像(含中间映像层,默认情况下,过滤掉中间映像层) --digests 显示镜像的摘要信息 -f 显示满足条件的镜像 --format 指定返回值的模板文件 --no-trunc 显示完整的镜像信息 -q 只显示镜像ID
docker rmi 删除本地一个或多个镜像 -f 强制删除 docker tag 标记本地镜像,将其归入某一仓库 docker tag [OPTIONS] IMAGE[:TAG] [REGISTRYHOST/][USERNAME/]NAME[:TAG]
docker build 用于使用Dockerfile 创建镜像 --buil-arg=[] 设置镜像创建时的变量 -f 指定要使用的Dockerfile路径 -m 设置内存最大值 --no-cache :创建镜像的过程不使用缓存 --pull 尝试去更新镜像的新版本 --quiet,-q 安静模式,成功后只输出镜像 ID --rm 设置镜像成功后删除中间容器 --ulimit Ulimit配置 --tag,-t 镜像的名字及标签,通常 name:tag 或者 name 格式;可以在一次构建中为一个镜像设置多个标签。 --network 默认 default。在构建期间设置RUN指令的网络模式
docker info 显示docker 系统的信息,包括镜像和容器数 docker version 显示docker 版本信息
3. docker-compose
3.1 安装
# sudo curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# chmod +x /usr/local/bin/docker-compose
3.2 用法
-f 指定使用的 yaml 文件位置 up -d 启动容器项目 ps 显示所有容器信息 pause 暂停容器 unpause 恢复暂停 restart 重新启动容器 logs 查看日志信息 rm 删除容器 config -q 验证yaml 配置文件是否正确 stop 停止容器 start 启动容器
yaml 文件示例
version:'2' services: db: images:mysql5.7 restart:always environment: MYSQL_ROOT_PASSWORD:somewordpress MYSQL_DATABASE:wordpress MYSQL_USER:wordpress MYSQL_PASSWORD:wordpress wordpress: depend_on: -db images:wordpress:latest restart:always port: -"8080:80" environment: WORDPRESS_DB_HOST:db:3306 WORDPRESS_DB_USER:wordpress WORDPRESS_DB_PASSWORD:wordpress
四、docker 镜像管理
1. 镜像的特性
容器创建时需要指定镜像,每个镜像都由唯一的标识 Image ID,和容器的Container ID 一样,默认128位,可以使用前16 位缩略形式,也可以使用镜像名与版本号两部分组合唯一标识,如果省略版本号,默认使用最新版本标签(latest)
镜像的分层:docker 的镜像通过联合文件系统(union filesystem)将各层文件系统叠加在一起。
>bootfs:用于系统引导的文件系统,包括 bootloader 和 kernel,容器启动完成后会被卸载以节省内存资源
>rootfs:位于 bootfs 之上,表现为 docker 容器的根文件系统
>>传统模式中,系统启动时,内核挂载 rootfs 时首先将其挂载为"只读"模式,完整性自检完成后将其挂载为读写模式
>>docker 中,rootfs 由内核挂载为"只读"模式,而后通过 UFS 技术挂载一个"可写"层
2. 容器装换为镜像
# docker commit 容器ID/容器名 新名 [root@centos2 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f2c8da58d4da nginx:latest "nginx -g 'daemon ..." 5 hours ago Up 3 seconds 0.0.0.0:81->80/tcp nginx [root@centos2 ~]# docker commit nginx nginx2 sha256:9722e0bba4cce4687d5d72db946924ad4c94ae50c4b1dcbe248017c978d4275f [root@centos2 ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx2 latest 9722e0bba4cc 4 seconds ago 161 MB nginx latest c7460dfcab50 16 hours ago 126 MB [root@centos2 ~]# docker commit f2c8da58d4da nginx3 sha256:885ffc103241b827b85ba5cd02970652ea970aff880aa48dffead9f61788895d [root@centos2 ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx3 latest 885ffc103241 1 second ago 161 MB nginx2 latest 9722e0bba4cc About a minute ago 161 MB nginx latest c7460dfcab50 16 hours ago 126 MB
3. Dockerfile
Dockerfile 是一种被 Docker 程序解释的脚本,Dockerfile 由一条一条的指令组成,每条指令对于Linux 下面的一条命令。docker 程序将这些 Dockerfile 指令翻译成真正的 Linux 命令。Dockerfile 有自己的书写格式和支持的命令,Docker 程序解决这些命令间的依赖关系,类似于 Makefile。Dockerfile 程序将读取 Dockerfile,根据指令生成定制的 image。
命令
# docker build -t learn/jdk-tomcat .
[root@centos2 ~/Dockerfile-Tomcat]# docker build -t learn/jdk-tomcat . Sending build context to Docker daemon 104.3 MB Step 1/8 : FROM hub.c.163.com/public/centos:6.7 6.7: Pulling from public/centos a3ed95caeb02: Pull complete a2086e9272f4: Pull complete fe7556d2a571: Pull complete e4503b9682fe: Pull complete 970241ec8701: Pull complete c057cfc98b71: Pull complete d104dceb2fbf: Pull complete 91c5984f9881: Pull complete 9e2158881254: Pull complete Digest: sha256:318d49272d1ef825831051c558ccb24237f0e95ea0f30dde2c1e6cab11d62ecb Status: Downloaded newer image for hub.c.163.com/public/centos:6.7 ---> 63751eaadece Step 2/8 : MAINTAINER wangyang@itxdl.cn ---> Running in 5cc297bff9d8 ---> b9c204139887 Removing intermediate container 5cc297bff9d8 Step 3/8 : ADD ./apache-tomcat-7.0.42.tar.gz /root ---> aefd1a02bedc Removing intermediate container 3cffb85dd608 Step 4/8 : ADD ./jdk-7u25-linux-x64.tar.gz /root ---> 0195ce7bac1e Removing intermediate container 3f26dd64eb17 Step 5/8 : ENV JAVA_HOME /root/jdk1.7.0_25 ---> Running in 709e51981d30 ---> f1ca5fb54b60 Removing intermediate container 709e51981d30 Step 6/8 : ENV PATH $JAVA_HOME/bin:$PATH ---> Running in ad5c583d4b1f ---> e2c47d19484d Removing intermediate container ad5c583d4b1f Step 7/8 : EXPOSE 8080 ---> Running in 2b702b3e53af ---> 2d6cda9060be Removing intermediate container 2b702b3e53af Step 8/8 : ENTRYPOINT /root/apache-tomcat-7.0.42/bin/startup.sh && tailf /root/apache-tomcat-7.0.42/logs/catalina.out ---> Running in a71c4da51e81 ---> 34a8bacdbb50 Removing intermediate container a71c4da51e81 Successfully built 34a8bacdbb50 [root@centos2 ~/Dockerfile-Tomcat]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE learn/jdk-tomcat latest 34a8bacdbb50 14 seconds ago 642 MB nginx3 latest 885ffc103241 24 minutes ago 161 MB nginx2 latest 9722e0bba4cc 25 minutes ago 161 MB nginx latest c7460dfcab50 17 hours ago 126 MB hub.c.163.com/public/centos 6.7 63751eaadece 3 years ago 393 MB [root@centos2 ~/Dockerfile-Tomcat]# docker run --name tomcat -p 8081:8080 -d learn/jdk-tomcat 75bbe56ed2727c2950049d0258108b45d9bfd23df2aefe3d93b95855e5c33205 [root@centos2 ~/Dockerfile-Tomcat]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 75bbe56ed272 learn/jdk-tomcat "/bin/sh -c '/root..." 3 seconds ago Up 2 seconds 22/tcp, 0.0.0.0:8081->8080/tcp tomcat f2c8da58d4da nginx:latest "nginx -g 'daemon ..." 6 hours ago Up 27 minutes 0.0.0.0:81->80/tcp nginx [root@centos2 ~/Dockerfile-Tomcat]# iptables -A INPUT -p tcp --dport=8081 -j ACCEPT
Dockerfile 语法
1. FROM(指定基础 image)
构建指令,必须指定且需要在 Dockerfile 其他指令的前面。后续的指令都依赖于该指令指定的image。FROM 指令指定的基础image 可以是官方远程仓库中的,也可以位于本地仓库。
example: FROM centos:7.2 FROM centos
2. MAINTAINER(用来指定镜像创建者信息)
构建指令,用于将 image 的创建者相关的信息写入到 image 中。当我们对该 image 执行 docker inspect 命令时,输出中有相应的字段记录该信息
example: MAINTAINER nanshan "emailname@163.com"
3. RUN(安装软件用)
构建指令,RUN 可以运行任何被基础 image 支持的命令。如基础 image 选择 centos,那么软件管理部分只能使用 centos 的包管理命令
example: RUN cd /tmp && curl -L 'http://archive.apache.org/dist/tomcat/tomcat-7/v7.0.8/bin/apache-tomcat-7.0.8.tar.gz' | tar -zx RUN ["/bin/bash","-c","echo 123"]
4. CMD(设置 container 启动时执行的操作)
设置指令,用于 container 启动时指定的操作。该操作可以是执行自定义脚本,也可以是执行系统命令。该指令只能在文件中存在一次,如果有多个,则只执行最后一条
example: CMD echo "hello world"
5. ENTRYPOINT(设置 container 启动时执行的操作)
设置指令,指定容器启动时执行的命令,可以多次设置,但是只有最后一个有效。
example: ENTRYPOINT ls -l
该指令的使用分为两种情况,一种是独自使用,另一种和CMD 指令配合使用。当独自使用时,如果还使用了 CMD 命令且 CMD 是一个完整的可执行的命令,那么CMD 指令和 ENTRYPOINT 会互相覆盖,只有最后一个 CMD或 ENTRYPOINT 有效
#CMD 指令不会被执行,只有 ENTRYPOINT 指令被执行 CMD echo "hello world" ENTRYPOINT ls -l
另一种用法和 CMD指令配合使用来指定 ENTRYPOINT 的默认参数,这时 CMD 指令不是一个完整的可执行命令,仅仅是参数部分;ENTRYPOINT 指令只能使用JSON 方式指定执行命令,而不能指定参数
example: FROM centos CMD ["-l"] ENTRYPOINT ["/usr/bin/ls"]
6. USER(设置 container 容器的用户)
设置指令,设置启动容器的用户,默认是 root 用户
example: USER daemon = ENTRYPOINT ["memcached","-u","daemon"]
7. EXPOSE(指定容器需要映射到宿主机的端口)
设置指令,该指令会将容器中的端口映射成宿主机中的某个端口。当你需要访问容器的时候,可以不是用容器的IP地址而是使用宿主机器的IP地址和映射后的端口。要完成整个操作需要两个步骤,首先在Dockerfile使用EXPOSE设置需要映射的容器端口,然后在运行容器的时候指定-p选项加上EXPOSE设置的端口,这样EXPOSE设置的端口号会被随机映射成宿主机器中的一个端口号。也可以指定需要映射到宿主机器的那个端口,这时要确保宿主机器上的端口号没有被使用。EXPOSE指令可以一次设置多个端口号,相应的运行容器的时候,可以配套的多次使用-p选项。
example: 映射一个端口 EXPOSE 81 docker run -p 81:80 --name nginx -d nginx 映射多个端口 EXPOSE port1 port2 port3 docker run -p port1 -p port2 -p port3 image docker run -p host_port1:port1 -p host_port2:port2 host_port3:port3 image
8. ENV(用于设置环境变量)
构建指令,在image 中设置一个环境变量
example: 设置了后,后续的 RUN 命令都可以使用,container 启动后,可以通过 docker inspect 查看这个环境变量,也可以通过在 docker run --env key=value 时设置或修改环境变量。假如安装了JAVA 程序,需要设置JAVA_HOME,那么就可以在 Dockerfile 中这样写: ENV JAVA_HOME /path/to/java/dirent
9. ADD(从src 复制文件到 container 的 dest 路径)
example: ADD <src> <dest> <src>是相对被构建的源目录的相对路径,可以是文件或目录的路径,也可以是一个远程的文件 url; <dest>是 container 中的绝对路径
10. COPY(从src 复制文件到 container 的 dest 路径)
example:
COPY <src> <dest>
11. VOLUME(指定挂载点)
设置指令,使容器中的一个目录具有持久化存储数据的功能,该目录可以被容器本身使用,也可以共享给其他容器使用。我们知道容器使用的是AUFS,这种文件系统不能持久化数据,当容器关闭后,所有的更改都会丢失。当容器中的应用有持久化数据的需求时可以在Dockerfile中使用该指令
exampl: FROM base VOLUME ["/data"]
12. WORKDIR(切换目录)
设置指令,可以多次切换(相当于 cd 命令),对 RUN,CMD,ENTRYPOINT 生效
example: WORKDIR /p1 WORKDIR p2 RUN vim 1.txt
13. ONBUILD(在子镜像中执行)
ONBUILD 指定的命令在构建镜像时并不执行,而是在它的子镜像中执行
example: ONBUILD ADD ./app/src ONBUILD RUN /usr/local/bin/python-build --dir /app/src
4. 镜像的导入与导出
# docker save -o xxx.tar xxx:xxx # 导出 # docker load -i xxx.tar # 导入 # docker save -o nginx:latest nginx.tar # docker load -i nginx.tar
五、镜像仓库构建
1. 官方仓库构建
# docker run --name registry -d -v /opt/registry:/var/lib/registry -p 5000:5000 --restart=always registry # 启动 # vim /etc/docker/daemon.json { "insecure-registries": ["192.168.80.129:5000"] } # 新建文件
# systemctl restart docker
1.1 上传测试
[root@centos2 ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE learn/jdk-tomcat latest 34a8bacdbb50 2 days ago 642 MB nginx3 latest 885ffc103241 2 days ago 161 MB nginx2 latest 9722e0bba4cc 2 days ago 161 MB nginx latest c7460dfcab50 3 days ago 126 MB registry latest f32a97de94e1 10 months ago 25.8 MB hub.c.163.com/public/centos 6.7 63751eaadece 3 years ago 393 MB [root@centos2 ~]# docker tag nginx:latest 192.168.80.129:5000/nginx:1.0 [root@centos2 ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE learn/jdk-tomcat latest 34a8bacdbb50 2 days ago 642 MB nginx3 latest 885ffc103241 2 days ago 161 MB nginx2 latest 9722e0bba4cc 2 days ago 161 MB nginx latest c7460dfcab50 3 days ago 126 MB 192.168.80.129:5000/nginx 1.0 c7460dfcab50 3 days ago 126 MB registry latest f32a97de94e1 10 months ago 25.8 MB hub.c.163.com/public/centos 6.7 63751eaadece 3 years ago 393 MB [root@centos2 ]# docker push 192.168.80.129:5000/nginx:1.0 The push refers to a repository [192.168.80.129:5000/nginx] c26e88311e71: Pushed 17fde96446df: Pushed 556c5fb0d91b: Pushed 1.0: digest: sha256:b4f0031063ab09a0945217020bde9e6774602d4177070e8ad2138bd0f88ad6e8 size: 948 [root@centos2 ]# !curl curl -XGET http://192.168.80.129:5000/v2/_catalog #查看已有镜像
{"repositories":["nginx"]}
1.2 客户端设置并测试
[root@localhost ]# vim /etc/docker/daemon.json { "insecure-registries": ["192.168.80.129:5000"] } [root@localhost /etc/systemd/system]# systemctl restart docker [root@localhost /etc/systemd/system]# docker pull 192.168.80.129:5000/nginx:1.0 Trying to pull repository 192.168.80.129:5000/nginx ... 1.0: Pulling from 192.168.80.129:5000/nginx 0333ebe13ca6: Pull complete a25dda6df773: Pull complete 7d4a713e1acb: Pull complete Digest: sha256:b4f0031063ab09a0945217020bde9e6774602d4177070e8ad2138bd0f88ad6e8 Status: Downloaded newer image for 192.168.80.129:5000/nginx:1.0 [root@localhost ]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE 192.168.80.129:5000/nginx 1.0 c7460dfcab50 3 days ago 126 MB docker.io/hello-world latest fce289e99eb9 12 months ago 1.84 kB [root@localhost ]# docker run --name nginx -p 81:80 -d 192.168.80.129:5000/nginx:1.0 5de23c8cd8f978529ff088cd97793d50f1e127a6168b7f5d653665291b331f5f [root@localhost ]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 5de23c8cd8f9 192.168.80.129:5000/nginx:1.0 "nginx -g 'daemon ..." 2 seconds ago Up 2 seconds 0.0.0.0:81->80/tcp nginx [root@localhost ]# firewall-cmd --zone=public --add-port=81/tcp success
2.