Docker 容器(二)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,高可用系列 2核4GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: Docker 是 Docker.Inc 公司开源的一个基于 LXC技术之上构建的Container容器引擎, 源代码托管在 GitHub 上, 基于Go语言并遵从Apache2.0协议开源。 Docker是通过内核虚拟化技术(namespaces及cgroups等)来提供容器的资源隔离与安全保障等。由于Docker通过操作系统层的虚拟化实现隔离,所以Docker容器在运行时,不需要类似虚拟机(VM)额外的操作系统开销,提高资源利用率。

Docker commit

参考官方文档https://docs.docker.com/engine/reference/commandline/commit/
docker commit [选项] <容器ID或容器名> [<仓库名>[:<标签>]]
-a :提交的镜像作者
-c :使用Dockerfile指令来创建镜像
-m :提交时的说明文字
-p :在commit时,将容器暂停
root@docker:~# docker commit -a "lvxinjie.cn" -m "my mysql" a404c6c174a2  mysql:v1 
sha256:37af1236adef1544e8886be23010b66577647a40bc02c0885a6600b33ee28057
root@docker:~# docker images mysql:v1
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
mysql               v1                  37af1236adef

Docker理念

将运用与运行的环境打包形成容器运行,运行可以伴随着容器,但是我们对数据的要求希望是持久化的
容器之间希望有可能共享数据
docker容器产生的数据,如果不能通过docker commit生成新的镜像,使得数据作为镜像的一部分保存下来,那么当容器删除后,数据自然也就没了
所以引出数据卷

什么是数据卷

类似redis里面的rdb和aof文件
数据共享和数据持久化

数据卷特点

数据卷可在容器之间共享或重用数据

卷中的更改可以直接生效

数据卷中的更改不会包括在镜像的更新中

数据卷的生命周期一直持续到没有容器使用它为止

添加数据卷

命令添加
DockerFile 添加
注:下面将深入讲解DockerFile

命令添加

docker run -it -v /宿主机绝对路径:/容器内路径  镜像名
[root@docker ~ ]# docker run -it -v /data:/data centos
[root@b9452b2d107d /]# ll -d /data/
drwxr-xr-x 2 root root 6 5月  10 11:06 /data/
[root@b9452b2d107d /]# exit
exit
[root@docker ~ ]# ll -d /data
drwxr-xr-x 2 root root 6 5月  10 11:06 /data/
注:此data目录若不存在,则自动创建

查看数据是否挂载成功

[root@docker ~ ]# df -h
文件系统        容量  已用  可用 已用% 挂载点
/dev/sda3        20G  3.2G   17G   17% /
devtmpfs        477M     0  477M    0% /dev
tmpfs           488M     0  488M    0% /dev/shm
tmpfs           488M  7.7M  480M    2% /run
tmpfs           488M     0  488M    0% /sys/fs/cgroup
/dev/sda1       197M  102M   95M   52% /boot
tmpfs            98M     0   98M    0% /run/user/0
overlay          20G  3.2G   17G   17% /var/lib/docker/overlay2/02cb0e7ea8ee17895f6d697eaee60507695fc59d4a76cbec9ba14f1d4f861fb8/merged

容器和宿主机之间数据共享

640.png容器停止后,主机修改后数据是否同步

640.png

启动带入权限

docker run -it -v /宿主机绝对路径:/容器内路径:ro  镜像名   ro --> read only

DockerFile添加

# 根下新建data文件夹斌进入
mkdir  /data
cd /data
# 可在dockerfile使用VOLUME指令给镜像添加一个或多个数据库
VOLUME["/data1","/data2","/data3"]
# file构建
# 开始编写dockerfile
$ vim Dockefile
FROM centos
VOLUME ["/data1","/data2"]
CMD echo "file is ok --------success"
CMD /bin/bash
# build生成镜像  --> 获得新镜像
docker build -f /data/Dockerfile -t ajie/centos .
# run 容器
docker run -it ajie/centos /bin/bash
注:若启动容器后提示permission denied
在挂载目录后面夹入 --privilegd=true

数据卷容器

命名的容器挂载数据卷,其它容器挂载这个(父容器)实现数据共享,挂载数据卷的容器称之为数据卷容器

小测试

dc01 dc02 dc03 虚拟化三台步骤如下

先启动父容器dc01

[root@docker /data ]# docker run -it --name dc01  ajie/centos
[root@56661c67e139 /]# cd /data2
[root@56661c67e139 data2]# touch test2.txt
[root@docker /data ]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS               NAMES
56661c67e139        ajie/centos         "/bin/sh -c /bin/bash"   About a minute ago   Up About a minute                       dc01

dc02/dc03继承dc01

[root@docker /data ]# docker run -it --name dc02 --volumes-from dc01 ajie/centos
[root@4e7ea72ceb06 /]# cd data2
[root@4e7ea72ceb06 data2]# ls
test2.txt
[root@4e7ea72ceb06 data2]# touch test02.txt
[root@docker /data ]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS               NAMES
4e7ea72ceb06        ajie/centos         "/bin/sh -c /bin/bash"   About a minute ago   Up About a minute                       dc02
56661c67e139        ajie/centos         "/bin/sh -c /bin/bash"   5 minutes ago        Up 5 minutes                            dc01
[root@docker ~ ]# docker run -it --name dc03 --volumes-from dc01 ajie/centos
[root@8034ec2956fc /]# cd /data2/
[root@8034ec2956fc data2]# ls
test02.txt  test2.txt
[root@8034ec2956fc data2]# touch dc03.txt
[root@8034ec2956fc data2]# ls
dc03.txt  test02.txt  test2.txt
[root@docker ~ ]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
8034ec2956fc        ajie/centos         "/bin/sh -c /bin/bash"   46 seconds ago      Up 45 seconds                           dc03
4e7ea72ceb06        ajie/centos         "/bin/sh -c /bin/bash"   2 minutes ago       Up 2 minutes                            dc02
56661c67e139        ajie/centos         "/bin/sh -c /bin/bash"   6 minutes ago       Up 6 minutes                            dc01

回到dc01可以看到02/03各自添加的都能共享

[root@docker ~ ]# docker attach dc01
[root@56661c67e139 data2]# ls 
dc03.txt  test02.txt  test2.txt

删除dc01 dc02修改后dc03能否访问

[root@docker ~ ]# docker rm -f dc01
[root@docker ~ ]# docker attach dc02
[root@4e7ea72ceb06 data2]# ls
dc03.txt  test02.txt  test2.txt
[root@4e7ea72ceb06 data2]# touch dc02.txt
[root@docker ~ ]# docker attach dc03
[root@8034ec2956fc data2]# ls
dc02.txt  dc03.txt  test02.txt  test2.txt

新建dc04继承dc03后在删除dc03(动手操作一下)

# code

结论;容器之间的配置信息的传递,数据卷的生命周期一直持续到没有容器使用它为止

什么是DockerFile?

DockerFile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本
类似ansible剧本,有内置命令

构建三步骤

编写dockerfile文件
docker build
docker run

文件格式

FROM centos:7
ENV container docker
MAINTAINER The CentOS Project <cloud-ops@centos.org>
RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*;
VOLUME [ "/sys/fs/cgroup" ]
CMD ["/usr/sbin/init"]

构建过程解析

内部基础知识

每条保留字指令都必须为大写字母且后面要跟随至少一个参数
按照指定从上到下,顺序执行
# 表示注释
每条指令都会创建一个新的镜像层,并对镜像进行提交

流程

docker 从基础镜像运行一个容器
执行一条指定并对日前作出修改
执行类似docker commit 的操作提交一个新的镜像层
docker 再基础刚提交的镜像运行一个新容器
执行dockerfile中的下一条指令直到所有的指令都执行完成

总结

从应用软件的角度看,DockerFile,Docker镜像与Docker容器分别代表软件的三个不同阶段
DcokerFile是软件的原材料
Docker镜像是软件的交付品
Docker容器则可以认为是软件的运行状态
DockerFile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石。

保留字指令

FROM
基础镜像,当前新镜像是基础那个镜像的
MAINTAINER
镜像维护者的姓名和邮箱地址
RUN
容器构建时需要的运行命令
EXPOSE
当前容器对外暴露的端口
WORKDIR
指定在创建容器后,终端默认登录进来的工作目录,一个路径
ENV
用来在构建镜像过程中设置的环境变量
ADD
将宿主机目录下的文件拷贝到镜像里且ADD命令会自动处理URL和tar压缩包
COPY
类似ADD,拷贝文件和目录到镜像中
将从构建上下文目录中<源路径>的文件/目录复制到新的一层镜像内的<目标路径>位置
COPY src dest
COPY  [ "src","dest" ]
VOLUME
容器数据卷,用于数据卷保存和持久化工作
CMD
指定一个容器启动时要运行的命令
Dockerfile中可以有多个CMD命令,但只有最后一个生效,CMD会被docker run之后的参数替换 
ENTRYPOINT
指定一个容器启动时要运行的命令
ENTRYPOINT和CMD命令一样,都是在指定容器启动程序及参数
ONBUILD
当构建一个被继承的DockerFile时运行命令,父镜像在被继承后,父镜像的onbuild被触发

案例

Base镜像(scratch) Docker Hub中99%的镜像都是通过在base镜像中安装和配置需要的软件构建出来的

自定义镜像mycentos
  编写
    自定义默认路径
    vim功能
    ifconfig功能
  FROM centos
  ENV mypath /tmp
  WORKDIR $mypath
  RUN yum install vim -y &>/dev/null
  RUN yum install net-tools -y &>/dev/null
  EXPOSE 80
  CMD /bin/bash
  构建
  docker build -f /data/mycentos -t name:tag .
  运行
  docker run -it mycentos:tag
  列出镜像的变更历史
  docker history mycentos
  导出镜像
  docker save -o mycentos.tar mycentos
  导入镜像
  docker load -i xxx

CMD/ENTRYPOINT 镜像案例

制作ip查询
curl -i url i 是请求
CMD演示
vim /data/ip1
FROM centos
RUN yum install -y curl &>/dev/null
CMD ["curl","-s","baidu.com"]
docker build -f /data/ip1 -t ip1 .
docker run -it ip1
ENTRYPOINT演示
vim /data/ip2
FROM centos
RUN yum install -y curl &>/dev/null
ENTRYPOINT ["curl","-s","baidu.com"]
docker build -f /data/ip2 -t ip2 .
docker run -it ip2 -i

Docker私有仓库

docker registry

docker-harbor

安装docker-compose

yum install -y python2-pip

这里使用pip安装,默认源为国外,可以使用国内加速,相关网站

    https://mirrors.tuna.tsinghua.edu.cn/help/pypi/

    pip加速操作命令

      pip install -i https://pypi.tuna.tsinghua.edu.cn/simple 
      pip -Upip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple

      继续安装docker-compose

        pip install docker-compose

        检查

          docker-compose version

          上传解压docker-harbor

          [root@docker01 ~]# cd /opt/
          [root@docker01 /opt]# ls
          harbor-offline-installer-v1.9.0-rc1.tgz
          [root@docker01 /opt]# tar zxf harbor-offline-installer-v1.9.0-rc1.tgz 
          [root@docker01 /opt]# ls
          harbor  harbor-offline-installer-v1.9.0-rc1.tgz
          [root@docker01 /opt]# cd harbor/

          修改配置文件

          [root@docker01 /opt/harbor]# egrep "10.0.1.11|123456" harbor.yml 
          hostname: 10.0.1.11
          harbor_admin_password: 123456

          安装

          [root@docker01 /opt/harbor]# ./install.sh

          修改docker信任仓库

          [root@docker01 /opt/harbor]# cat /etc/docker/daemon.json    
          {
                "registry-mirrors": ["http://hub-mirror.c.163.com"],
                "insecure-registries": ["http://10.0.1.11"] 
          }

          重启docker并上传镜像

            systemctl restart docker

            给镜像打标签并提交到dockerharbor

              [root@docker01 /opt/harbor]# docker login 10.0.1.11           
              Username: zhangya 
              Password: 
              WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
              Configure a credential helper to remove this warning. See
              https://docs.docker.com/engine/reference/commandline/login/#credentials-store
              Login Succeeded
              [root@docker01 ~]# docker run -d -p 8080:80 centos_kod:v1          
              78be80f7c2029b68e8943e38fa99131ec6709f798e63c94afb5a7fdfa4a8047c
              [root@docker01 ~]# docker ps|grep kod
              78be80f7c202        centos_kod:v1                                       "/bin/bash /init.sh"     15 seconds ago      Up 13 seconds            0.0.0.0:8080->80/tcp        tender_dirac
              [root@docker01 ~]# docker commit 78be80f7c202 10.0.1.11/linux/centos_kod:v1
              sha256:6bf1e1eef1969bcd4c82472aed945d4dda74a923c0d7dae91e38539676f8c240
              [root@docker01 ~/dockerfile/kod]# docker images
              REPOSITORY                      TAG                        IMAGE ID            CREATED             SIZE
              10.0.1.11/linux/centos_kod      v1                         6bf1e1eef196        13 minutes ago      465MB
              [root@docker01 /opt/harbor]# docker push 10.0.1.11/linux/centos_kod:v1

              在docker-harbor上查看

              网页登录 此教程略

              其他主机上下载镜像

                [root@docker02 ~]# cat /etc/docker/daemon.json 
                {
                      "registry-mirrors": ["http://hub-mirror.c.163.com"],
                      "insecure-registries": ["http://10.0.1.11"],
                      "insecure-registries": ["https://10.0.1.11"] 
                }
                [root@docker02 ~]# docker pull 10.0.1.11/linux/centos_kod:v1

                Docker四种网络模式

                实现原理

                Docker使用Linux桥接(参考《Linux虚拟网络技术》),在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信。

                Docker网桥是宿主机虚拟出来的,并不是真实存在的网络设备,外部网络是无法寻址到的,这也意味着外部网络无法通过直接Container-IP访问到容器。如果容器希望外部访问能够访问到,可以通过映射容器端口到宿主主机(端口映射),即docker run创建容器时候通过 -p 或 -P 参数来启用,访问容器的时候就通过[宿主机IP]:[容器端口]访问容器。

                四类网络模式

                Docker网络模式 配置 说明
                host模式 –net=host 容器和宿主机共享Network namespace。
                container模式 –net=container:NAME_or_ID 容器和另外一个容器共享Network namespace。kubernetes中的pod就是多个容器共享一个Network namespace。
                none模式 –net=none 容器有独立的Network namespace,但并没有对其进行任何网络设置,如分配veth pair 和网桥连接,配置IP等。
                bridge模式 –net=bridge (默认为该模式)

                host模式

                如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。

                使用host模式的容器可以直接使用宿主机的IP地址与外界通信,容器内部的服务端口也可以使用宿主机的端口,不需要进行NAT,host最大的优势就是网络性能比较好,但是docker host上已经使用的端口就不能再用了,网络的隔离性不好。

                Host模式如下图所示:

                container模式

                这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。

                Container模式示意图:

                none模式

                使用none模式,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等。

                这种网络模式下容器只有lo回环网络,没有其他网卡。none模式可以在容器创建时通过--network=none来指定。这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性。

                None模式示意图:


                bridge模式

                当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。

                从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。在主机上创建一对虚拟网卡veth pair设备,Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到docker0网桥中。可以通过brctl show命令查看。

                bridge模式是docker的默认网络模式,不写--net参数,就是bridge模式。使用docker run -p时,docker实际是在iptables做了DNAT规则,实现端口转发功能。可以使用iptables -t nat -vnL查看。

                bridge模式如下图所示:


                相关实践学习
                每个IT人都想学的“Web应用上云经典架构”实战
                本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
                MySQL数据库入门学习
                本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
                相关文章
                |
                3月前
                |
                存储 监控 测试技术
                如何将现有的应用程序迁移到Docker容器中?
                如何将现有的应用程序迁移到Docker容器中?
                290 57
                |
                3月前
                |
                存储 监控 Java
                如何对迁移到Docker容器中的应用进行性能优化?
                如何对迁移到Docker容器中的应用进行性能优化?
                261 59
                |
                3月前
                |
                NoSQL Redis Docker
                使用Docker Compose工具进行容器编排的教程
                以上就是使用Docker Compose进行容器编排的基础操作。这能帮你更有效地在本地或者在服务器上部署和管理多容器应用。
                349 11
                |
                3月前
                |
                缓存 Java Docker
                如何对应用代码进行优化以提高在Docker容器中的性能?
                如何对应用代码进行优化以提高在Docker容器中的性能?
                227 1
                |
                2月前
                |
                安全 持续交付 Docker
                Docker:重塑现代软件交付的容器引擎
                Docker:重塑现代软件交付的容器引擎
                |
                2月前
                |
                存储 持续交付 Docker
                Docker:轻量级容器技术重塑应用交付
                Docker:轻量级容器技术重塑应用交付
                |
                2月前
                |
                Kubernetes Cloud Native 持续交付
                Docker:轻量级容器化技术解析
                Docker:轻量级容器化技术解析
                |
                2月前
                |
                运维 测试技术 Docker
                Docker:轻量级容器化技术革命
                Docker:轻量级容器化技术革命