Py学习  »  docker

docker入门

立刀流 • 3 年前 • 351 次点击  
阅读 6

docker入门

docker思想

  1. 集装箱

    将所有需要的内容放到不同的集装箱中,谁需要这些环境就直接拿到这个集装箱就可以了。

  2. 标准化

    1. 运输标准化,Docker有一个码头,所有上传的集装箱都在这个码头上,当谁需要某个环境,直接去搬运这个集装箱就可以。
    2. 命令标准化,docker提供了一些指令,帮助我们去操作获取。
    3. 提供了REST的API,衍生出了很多图形化界面,Rancher。
  3. 隔离性

    docker在运行集装箱内的内容时,会在linux内核中,单独开辟一个空间,这个空间不会影响到其他程序。

注册中心。(超级码头、上面放的就是集装箱)

镜像。(集装箱)

容器。(运行起来的镜像)

安装docker

#1.下载docker依赖环境
yum -y install yum-utils device-mapper-persistent-data lvm2
#2.设置下载docker的镜像源
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
#3.安装docker
yum makecache fast
yum -y install docker-ce
#4.启动,并设置开机自动启动,测试
#启动docker服务
systemctl start docker
#设置开机启动
systemctl enable docker
#测试
docker run hello-world
复制代码

我这里遇到几点问题

1.安装失败,重新执行yum -y install docker-ce安装即可;

2.启动失败,报错start request repeated too quickly for docker.service,用dockerd指令重新执行,看报错信息, Error while creating filesystem xfs on device docker-8:3-34889290-base: exit status 1 storage-driver=devicemapper。网上查询是由于XFS文件系统管理工具的版本太低,使用如下命令升级:yum update xfsprogs -y。再启动。查看状态systemctl status docker

3.启动成功后运行hello-world失败,报错docker: Cannot connect to the Docker daemon at unix:///var/run/docker.sock.,查了一圈资料感觉都不对。重新启动虚拟机,重启docker,再次运行,成功。

注:docker 版本(Docker version 19.03.12, build 48a66213fe)

docker中央仓库

  1. docker官方的中央仓库

  2. 国内镜像仓库,网易凤巢、daoclould....

    hub.daocloud.io/ 推荐

    我使用该网站拉取遇到的问题:

    docker pull daocloud.io/library/tomcat:8.5.15-jre8 无法下载,报509,证书验证失败

    解决方法:查看hub.daocloud.io/的证书,并下载它的二级…

  3. 公司内部采用私服的方式拉取(添加配置)

    #需要在/etc/docker/daemon.json添加配置,ip:port为私服地址
    {
    "registry-mirrors":["https://registry.docker-cn.com"],
    "insecure-registries":["ip:port"]
    }
    #重启两个服务
    systemctl daemon-reload
    systemctl restart docker
    复制代码

docker镜像

通过docker images可以查看已有的镜像

image-20200909153928273.png 通过docker pull 镜像名来从仓库中拉取指定镜像,通过docker search redis查看可用版本。

我们来拉取一个redis的最新镜像

image-20200909165232821.png

运行redis容器:docker run -itd --name redis-test -p 6379:6379 redis

参数解释:

OptionsMean
-i以交互模式运行容器,通常与 -t 同时使用;
-t为容器重新分配一个伪输入终端,通常与 -i 同时使用;
-d后台运行容器,并返回容器ID;
-p映射容器服务的 6379 端口到宿主机的 6379 端口。外部可以直接通过宿主机ip:6379 访问到 Redis 的服务。

通过docker ps查看容器运行信息,docker ps -a命令,查询所有的容器

image-20200909165658061.png 进入我们的redis容器

docker exec -it redis-test /bin/bash或者docker exec -it 容器id /bin/bash
复制代码

并尝试执行一条指令

image-20200909170210744.png

通过docker stop 容器id去停止一个容器,docker restart 容器id去重启一个容器。

镜像删除使用 docker rmi 命令,比如我们删除 hello-world 镜像:

 docker rmi hello-world 或 docker rmi 镜像id
 #停止全部容器
 docker stop $(docker ps -qa)
 #删除全部容器
 docker rm $(docker ps -qa)
复制代码

如果该镜像运行过,需要先删除容器,docker rm 容器id,否则会删除失败

镜像导入导出

#导出镜像
docker save -o ./test.images 镜像id
#导入镜像
docker load -i test.images
#修改镜像名称
docker tag 镜像id 新镜像名称:版本
#导出容器
docker export ./test.tar 镜像id
#导入容器,实质也是将容器运行时的镜像导入,并给导入的镜像命名
docker import ./test.tar mytest
复制代码

查看容器日志

docker logs -f 容器id
复制代码

清除没有被容器使用的镜像文件

docker image prune -af 
#清除多余的数据,包括停止的容器、多余的镜像、未被使用的volume等等
docker system prune -f 
复制代码

容器生命周期

容器的生命周期是容器可能处于的状态,容器的生命周期分为 5 种。

created:初建状态

running:运行状态

stopped:停止状态

paused: 暂停状态

deleted:删除状态

image-20201031114826169.png

docker应用

准备项目

准备mysql容器

#运行mysql容器,--name指定了容器的名字,指定了root用户的密码,冒号后tag参数指定了要运行的版本
docker run -d -p 3306:3306 --name mysql -e MYSQL_ROOT_PASSWORD=root daocloud.io/library/mysql:5.7.4
复制代码

遇到的问题

  1. Navicat连接不上

查询网上资料,大概就是两点。修改mysql用户的权限,允许远程连接;开放宿主机的3306端口,允许外部进行访问。这两点我都已经改过,却发现依然连接不上,于是继续修改,还发现一个要打开服务的,于是放开了http和mysql,然后我还是连接不上。。。。折腾2小时,已崩。决定第二天用tcpdump抓包一下3306端口,本机进行telnet访问,看是否进来。第二天重新开机,发现可以连接了,只能证明一件事:重启大法好!!!!

  1. 附上相关指令:

centos7默认防火墙为filewall

  • 放通端口 firewall-cmd --zone=public --add-port=3306/tcp --permanent firewall-cmd --reload 查看所有开放的端口 firewall-cmd --zone=public --list-ports

  • 放通服务

    查看可以打开的服务 firewall-cmd --get-services 添加一个服务 firewall-cmd --permanent --add-service=http 查看已经打开的服务 firewall-cmd --list-services

  • 放通mysql远程权限

    docker exec -it 容器id bash //进入容器

    mysql -uroot -p //进入mysql命令行

    use mysql

    ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'root'; //允许任何客户端连接

    flush privileges; //刷新权限

    SELECT user,host FROM user //host为%为都可以连接

准备tomcat容器

#启动tomcat,记得开放防火墙8080端口
docker run -itd --name tomcat -p 8080:8080 daocloud.io/library/tomcat:8.5.15-jre8
#通过命令将宿主机的内容复制到tomcat容器
#docker cp 文件名称 容器id:容器内部路径
docker cp test.tar f3:/usr/local/tomcat/webapps/
复制代码

数据卷

将宿主机的一个目录映射到容器的一个目录中,操作宿主机中文件,则容器内的也会发生变化

#创建数据卷
docker volume create 数据卷名称
#创建之后,默认会存放在一个目录下 /var/lib/docker/volumes/数据卷名称/_data
#查看数据卷详细信息
docker volume inspect tomcat
#查询全部数据卷
docker volume ls
#删除数据卷
docker volume rm 数据卷名称
#应用数据卷
#当映射数据卷时,数据卷如果不存在,docker会自动创建,这种方式会将容器中自带的文件也存储在默认存放路径中
docker run -v 数据卷名称:容器内部路径 镜像id
#直接指定一个路径作为数据卷的存放位置,这种不会默认存储容器中的文件(推荐)
docker run -v 路径:容器内部路径 镜像id
复制代码

在运行镜像时指定数据卷映射:

docker run -d -p 8080:8080 --name tomcat -v tomcat:/usr/local/webapps/ b43
复制代码

启动tomcat时指定数据卷,我们就会在/var/lib/docker/volumes/tomcat/_data下发现webapps中的东西

image-20200912115551716.png

docker自定义镜像

#创建Dokerfile文件,并且指定自定义镜像信息
#Dockerfile文件中常用的内容
from:指定当前自定义镜像依赖的环境
copy:将相对路径下的内容复制到自定义镜像中
workdir:声明镜像的默认工作目录
cmd:需要执行的命令(在workdir下执行的,cmd可以写多个,只以最后面一个为准)
复制代码

举例:自定义一个Dockerfile文件,并将我们的hellodocker.war部署,打包成自己的镜像

#Dockerfile内容
from daocloud.io/library/tomcat:8.5.15-jre8
copy hellodocker.war /usr/local/tomcat/webapps
复制代码
#通过docker指令制作镜像,把当前目录下的Dockerfile文件制作成一个镜像
docker bulid -t  镜像名称:[tag] .
复制代码

如下图:

image-20200912144255308.png

运行我们自定义的镜像:

image-20200912144524266.png

docker-compose的使用

之前运行一个镜像是需要加大量的参数,可以通过docker-compose编写这些参数。

docker-compose可以帮助我们批量管理容器,它是一个容器编排工具。

只需要通过一个docker-compose.yml文件去维护即可。

#下载docker-compose
#由于github网站太卡,可以用http://get.daocloud.io/去下载,根据实际情况修改版本
curl -L https://get.daocloud.io/docker/compose/releases/download/1.27.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
复制代码

docker-compose管理mysql和tomcat容器

编写yml配置信息,version版本对照:docs.docker.com/compose/com…

我的目录及数据存储:/opt/docker_mysql_tomcat

version: '3.8'
services:
  mysql:            #服务的名称
    restart: always   #代表只有docker启动,容器就跟着启动
    network_mode: bridge   #指定使用已有网络,不会生成默认的网络
    image: daocloud.io/library/mysql:5.7.4    #指定镜像
    container_name: mysql   #指定容器名称
    ports:
      - 3306:3306   #端口号映射
    environment:
      MYSQL_ROOT_PASSWORD: root   #指定root用户密码
      TZ: Asia/shanghai     #指定时区
    volumes:
      - /opt/docker_mysql_tomcat/mysql_data:/var/lib/mysql   #映射数据卷
  tomcat:
    restart: always
    network_mode: bridge


    

    image: docker-tomcat:1.0.0
    container_name: docker-tomcat
    ports:
      - 8080:8080
    environment:
      TZ: Asia/shanghai
    volumes:
      - /opt/docker_mysql_tomcat/tomcat_webapps:/usr/local/tomcat/webapps
      - /opt/docker_mysql_tomcat/tomcat_logs:/usr/local/tomcat/logs
复制代码

使用docker-compose命令管理容器

在使用docker-compose命令时,默认会在当前目录下找docker-compose.yml文件

#第一次启动,在docker-compose文件所在目录下
docker-compose up -d
#停止
docker-compose stop
#开启
docker-compose start
#重启
docker-compose restart
#停止并删除
docker-compose down
#查看
docker-compose ps
#查看日志
docker-compose logs -f 
复制代码

遇到的问题

  1. 按照以上配置启动,一切正常,但是无法访问,监听端口也没有任何请求进来

排查:先确认是否是宿主机问题导致。把该doker-compose启动的容器停掉,换成命令行式的启动一个镜像,发现可以访问(一个插曲,我启动的tomcat映射的宿主机8081端口,该端口没有放开,本地却可以访问到),说明服务虚机应该没有问题。

  1. 搜索docker-compose启动正常,服务无法访问的问题,也没有太多有效信息。这里我想起了之前了解过一点点docker容器会自己生成一套网络相关的东西,不同的网络模式会造成无法访问。

    #查询已配置的网络
    docker network ls
    #结果如下,其中docker_mysql_tomcat_default正式默认生成的
    NETWORK ID          NAME                          DRIVER              SCOPE
    2a460ca90250        bridge                        bridge              local
    3e0eb402b8e4        docker_mysql_tomcat_default   bridge              local
    cc495b89bd29        host                          host                local
    a300f2ee0209        none                          null                local
    #比较命令行启动的容器信息与docker-compose启动的容器信息
    docker inspect 容器id
    #配置docker-compose的网络,在每个容器名字下再添加一行,使用已有的网络,上面配置已添加
    network_mode: bridge
    复制代码
  2. 查看网络的具体配置信息

    #docker network ls中得到的NAME
    docker network inspect 网络名
    复制代码
  3. 不配置网络就会默认新建一个,为什么新建的网桥无法与宿主机通信?

    这个问题折磨了我许久,最终解决。先说结论,原因在于linux内核版本太低,需要升级内核。

    我是从这篇博客得到的启发:blog.csdn.net/coolfishbon…

    升级后,再次重新创建一个网桥,随便启动一个镜像用这个建好的网桥,进入容器内部,ping自己的网关,在ping自己的虚机地址,都可以ping通,说明已经可以正常的使用了。

docker-compose 配合Dockerfile使用

使用docker-compose.yml文件和Dockerfile文件在生成自定义镜像的同时启动当前镜像,并且由docker-compose去管理容器。

#yml文件
version: '3.8'
services:
  hello:
    restart: always
    build:              #构建自定义镜像
      context: ../      #指定Dockerfile文件所在目录
      dockerfile: Dockerfile
    image: hello:1.0.0
    container_name: hello
    ports:
      - 8081:8080
    environment:
      TZ: Asia/shanghai

复制代码

Dockerfile文件

from daocloud.io/library/tomcat:8.5.15-jre8
copy hellodocker.war /usr/local/tomcat/webapps
复制代码
#基于docker-compose以及Dockerfile构建自定义镜像
docker-compose up -d
#如果自定义镜像不存在,会进行构建,如果已经存在,则直接运行
#重新构建的话,用下面命令
docker-compose bulid 或者 docker-compose up -d --bulid
复制代码

#我的目录结构
/root/docker-tomcat/docker-compose   -------docker-compose.yml
/root/docker-tomcat   ----docker-compose  -------Dockerfile  ------hellodocker.war
复制代码

docker网络

Docker中的网络接口默认都是虚拟的接口,沙盒 ( Sandbox )网络 ( Network )、**端点 ( Endpoint )**三者形成了 Docker 网络的核心模型,也就是容器网络模型。我们看下docker的网络模型

image.png 启动docker会创建一个docker0的默认网桥,用来与宿主机和容器进行通信,网桥上有一个地址段与网关,每个容器的ip都从地址段中进行获取。

docker的默认网络

$ docker network ls
NETWORK ID          NAME                DRIVER
7fca4eb8c647        bridge              bridge
9f904ee27bf5        none                null
cf03ee007fb4        host                host
复制代码

docker的网络模式一个有下面几种:

1)bridge模式,--net=bridge(默认)
这是dokcer网络的默认设置,为容器创建独立的网络命名空间,容器具有独立的网卡等所有单独的网络栈,是最常用的使用方式。
在docker run启动容器的时候,如果不加--net参数,就默认采用这种网络模式。安装完docker,系统会自动添加一个供docker使用的网桥docker0,我们创建一个新的容器时,
容器通过DHCP获取一个与docker0同网段的IP地址,并默认连接到docker0网桥,以此实现容器与宿主机的网络互通。
 
2)host模式,--net=host
这个模式下创建出来的容器,直接使用容器宿主机的网络命名空间。
将不拥有自己独立的Network Namespace,即没有独立的网络环境。它使用宿主机的ip和端口。
 
3)none模式,--net=none
为容器创建独立网络命名空间,但不为它做任何网络配置,容器中只有lo,用户可以在此基础上,对容器网络做任意定制。
这个模式下,dokcer不为容器进行任何网络配置。需要我们自己为容器添加网卡,配置IP。
因此,若想使用pipework配置docker容器的ip地址,必须要在none模式下才可以。
 
4)Overlay模式,--net=overlay
容器在两个跨主机进行通信的时候,是使用overlay network这个网络模式进行通信,如果使用host也可以实现跨主机进行通信,直接使用这个物理的ip地址就可以进行通信。
 
5)用户自定义:docker 1.9版本以后新增的特性,允许容器使用第三方的网络实现或者创建单独的bridge网络,提供网络隔离能力。
复制代码

网络相关操作

#创建指定网段、网关的网络,-d指定什么模式
docker network create -d bridge --subnet=172.22.0.0/24 --gateway=172.22.0.1 my_net
#创建的网络用ifconfig查看,都是br-{networkid},如果要展示网络名,可以这样
docker network create -d bridge --subnet=172.22.0.0/24 --gateway=172.22.0.1 my_net -o com.docker.network.bridge.name=my_net
#查看已有的网络
docker network ls
#删除一个网络
docker network rm 网络名
#查看网络信息
docker network inspect 网络名

复制代码

docker CI、CD

CI介绍

CI(continuous intergration)持续集成

持续集成:编写代码,提交git,将项目重新构建并测试。

搭建gitlab服务器

  1. 创建一个全新虚拟机,至少4G的内存

  2. 安装docker以及docker-compose

  3. 编写docker-compose.yml文件,修改虚机ssh的端口号,因为gitlab要占用22端口

    镜像地址:github.com/CCC1004/git… 整个下载过程可能比较长

    version '3'
    services:
      gitlab:
        image: 'twang2218/gitlab-ce-zh:11.1.4'
        container_name: 'gitlab'
        restart: always
        privileged: true
        hostname: 'gitlab'
        environment:
          TZ: 'Asia/shanghai'
          GITLAB_OMNIBUS_CONGIG: |
          external_url 'http://192.168.199.110'  #宿主机ip
          gitlab_rails['time_zone']='Asia/shanghai'
          gitlab_rails['smtp_enable']=true
          gitlab_rails['gitlab_shell_ssh_port']=22
        ports:
          - 80:80
          - 443:443
    
    
        
    
          - 22:22
        volumes:
          - /opt/docker_gitlab/config:/etc/gitlab
          - /opt/docker_gitlab/data:/var/opt/gitlab
          - /opt/docker_gitlab/logs:/var/log/gitlab
    复制代码

安装gitlab-runner

CD介绍

持续交付、持续部署

image-20200913212345623.png

通过gitlab-runner实时部署服务器环境,自测无问题后通过Jenkins部署测试环境,供测试人员测试,最后发布到生产环境。这就是CI、CD模型。

搭建Jenkins

编写docker-compose.yml

version '3'
services:
  jenkins:
    image: jenkins/jenkins
    restart: always
    container_name: jenkins
    ports:
      - 8888:8080
      - 5000:5000
    volumes:
      - ./data:/var/jenkins_home    #data目录授777权限
复制代码

登陆密码在日志中,安装插件【publish ssh】、【git parameter】

小结

这个教程呢,我是在b站找的一个视频然后进行学习的,整个实践过程中确实发现了好多问题,幸好最后都解决了。收获还是有的,可惜公司并没有使用容器技术、现在我都又快忘光了。。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/110589
 
351 次点击