Docker基本技能之程序开发基本够用系列

Docker基本技能之程序开发基本够用系列

  1. Docker能做什么
    简化配置,代码流水线管理,提高开发效率,隔离应用,整合服务器,调试能力,多租户,快速部署

    涉及技术:
    发布计划,持续集成,持续发布,持续测试,持续监控,持续改进版本管理,自动化,部署,监控

  2. Docker
    容器解决开发人员与运维之间的沟通,矛盾
    是devops的最佳解决方案。

安装:
https://yq.aliyun.com/articles/701709

centos 下卸载docker:
   yum  list installed | grep docker
   yum remove docker-ce.x86_64 d docker-ce-cli.x86_64 -y 
   rm -rf /var/lib/docker   //删除镜像

容器:对软件和其依赖的标准化打包,应用之间相互隔离,共享同一个os kernel,可以运行在很多主流的操作系统上
容器是app层面的隔离,虚拟化是物理资源层面的隔离

  1. docker-machine
    快速创建docker容器环境

  2. docker架构
    三个核心:镜像(Image),容器(Container),仓库(Repository)
    client(build pull run) – docker host(containers, images) --registry

底层技术支持:
Namespaces:做隔离pid,net,ipc,mnt,uts
Control group:做资源限制
Union file systems:Container和image的分层

  1. docker image
    文件和meta data的集合(root filesystem)
    分层的,并且每一层都可以添加改变删除文件,成为一个新的image
    不同的image可以共享相同的layer
    image本身是read-only的

命令:

   docker search [mysql]  搜索如mysql镜像文件
   docker image ls
   docker pull ubuntu:14.04
   docker pull bitnami/wordpress
  1. DIY docker image

附:
useradd -m username // -p 密码
passwd 密码
userdel -r username //vipw 命令可以在文件中直接删除某一用户,也要把群删掉 groupdel
groupadd docker
gpasswd -a username groupname //username添加到组groupname, -d 是删除

    新的用户下
    mkdir hello-world
    vim hello.c
    gcc -static hello.c -o hello
    ./hello.c

vim Dockerfile 编写文件
内容如下:

	FROM scratch       # scratch 是内置关键词,并不是一个真实存在的镜像。 FROM scratch 会使用一个完全干净的文件系统,不包含任何文件。
	ADD hello /         # 执行的是将当前目录下的 hello 添加到 容器镜像的 / 路径下。
	CMD ["/hello"]
	docker build -t rose/hello-world .   #其中 . 指当前路径下的文件
	docker image ls  
	docker run rose/hello-world
  1. Container
    通过Image创建(copy)
    在Image layer之上建立一个container layer(可读写)
    类别面向对象:类和实例
    Image负责的app的存储和分发,container负责运行app

命令:

	docker container ls -a
	docker run -it centos   //-it 交互式运行
	docker run -d  redis  //-d 后台运行
	docker ps  //查看运行的容器
	docker container stop 容器名   //停止容器

删除所有容器:
docker rm $(docker container ls -aq)
批量停止在运行中的容器
docker ps -a | grep 'Up' | awk '{print $1}'| xargs docker container stop

批量删除Exited状态的容器
docker ps -a | grep 'Exited' | awk '{print $1}'| xargs docker container rm

批量删除name为none的image
docker image ls | grep none | awk '{print $3}' | xargs docker image rm

  1. Dockerfile语法
    FROM centos # 使用base image 尽量使用官方image

    LABEL maintainer=“rose@gmail.com”
    LABEL version=“1.0”
    LABEL description=“this is description”
    这个LABEL Metadata不可少

    RUN yum update && yum install -y vim
    python-dev # 反斜线换行,为了避免无用分层,尽量合并多条命令

    WORKDIR /root # 相当于linux cd 到某一目录,尽量使用绝对目录

    ADD hello / # 将hello 加到/下
    ADD test.tar.gz / # 添加到根目录并解压
    WORKDIR /root
    ADD hello test/ # /root/test/hello
    WORKDIR /root
    COPY hello test/

大部分COPY优先于ADD,ADD还有解压功能,添加运程文件/目录请使用curl或者wget\

ENV MYSQL_VERSION 5.6 # 设置常量
RUN apt-get install -y mysql-server="${MYSQL_VERSION}"
&& rm -rf /var/lib/apt/lists/* #引用常量

VOLUME and EXPOSE 用于存储和网络
CMD and ENTRYPOINT

RUN vs CMD and ENTRYPOINT
RUN :执行命令并创建新的ImageLayer,创建镜像的时执行
CMD:设置容器启动后默认执行的命令和参数,每次容器启动都会执行
ENTRYPOINT:设置容器启动时运行的命令

shell格式:
    RUN apt-get install -y vim
    CMD echo "hello docker"
    ENTRYPOINT echo "hello docker"
Exec格式:
    RUN ["apt-get", "install", "-y", "vim"]
    CMD ["/bin/echo", "hello docker"]
    ENTRYPOINT ["/bin/echo", "hello docker"]   # "/bin/bash" 可以执行$之类的变量

CMD:
    容器启动时默认执行的命令
    若docker run制定了其他命令,CMD命令被忽略
    若定义了多个CMD, 只有最后一个会执行

ENTRYPOINT:
    让容器以应用程序或服务的形式运行
    不会被忽略,一定会执行

  1. push到docker hub
    ⚠️先注册hub账户 https://hub.docker.com/
    1.创建Dockerfile
    2.构建Image, docker build -t hh .
    3.打标签Image, docker tag 53427d838b8a cc/hh:1.10 # cc为docker hub id
    4.登录hub.docker, docker login
    5.上传Image, docker push cc/hh # 若仓库已存在push的名字要与此一致

  2. 项目容器化
    python3安装
    链接:https://blog.csdn.net/u013214212/article/details/81540840

容器起到隔离作用,代替在主机中多个venv或虚拟机
Dockerfile

	FROM qzkc/python2.7:v1
	LABEL maintainer="ccbp"
	RUN pip install flask
	COPY app.py /app/    # 这里app.py 和Dockerfile 同一路径下
	WORKDIR /app
	EXPOSE 5000
	CMD ["python","app.py"]
  1. Docker Network
    单机:Bridge Network,Host Network,None Network
    多机:Overlay Network

    网络:ping网络连通性,telnet验证服务的可用性

    Network space:
    docker run -d --name test1 busybox /bin/sh -c "while true;do sleep 3600;done"
    docker run -d --name test2 busybox /bin/sh -c "while true;do sleep 3600;done"

    查看容器ip
    docker exec 065c141a1fe5 ip a
    进入到容器,并ping操作
    docker exec -it 065c141a1fe5 /bin/bash
    ping x.x.x.x
    可以发现两个容器网络互通

    vepath
    连接两个容器命名空间

    容器运行时报错,WARNING: IPv4 forwarding is disabled. Networking will not work.
    /usr/lib/sysctl.d/00-system.conf 文件添加 net.ipv4.ip_forward=1

    Bridge:
    docker network ls //查看当前docker有哪些网络

    docker network inspect 9bb20d27fa23 //bridge的网络id

    yum install bridge-utils
    brctl show 命令查看桥接网

    可以看到容器连接到这个bridge网络接口docker0

    容器访问网络(外网)路径:
    Internet – eth0 – NAT – docker0 --[container1, container2…]

    NAT 使用iptables 实现技术

    自定义网桥:
    brctl addbr br0 //定义br0网桥

    容器之间link:
    场景:web应用容器 与 数据库容器的连接,怎么方便找到并访问

    docker run -d --name test2 --link test1 busybox /bin/sh -c "while true;do sleep 3600;done"
    进入到容器中:
    docker exec -it test2 /bin/sh

    可以ping test1 直接写容器名字,就可以找到这个容器(这样可以不知道容器的ip,通过名字也可访问)
    –link 是单向的,这个方式却用的不多

    新建bridge:
    docker network create -d bridge my-bridge //新建my-bridge
    docker network ls 查看
    brctl show

    创建test3 链接到my-bridge 网络接口
    docker run -d --name test3 --network my-bridge busybox /bin/sh -c "while true;do sleep 3600;done"
    docker network ls
    docker network inspect [NETWORK ID] //查看

    docker network connect my-bridge test2 //可以将my-bridge连接到test2容器上

    那么这时 my-bridge 上的test3 test2 之间可以通过ping 容器名的方式 相互之间可以连通。

    容器端口映射:-p

    docker run --name web -d nginx
    docker ps
    docker network ls
    docker network inspect 9bb20d27fa23  //默认连接到bridge上
    telnet 172.17.0.4 80
    curl http://172.17.0.4:80   //访问nginx网页的内容
    
    把这个80端口映射到本地上,
    docker rm web 
    docker run --name web -d -p 80:80 nginx   //按顺序是容器80映射到本地80端口
    

    host和none
    docker run -d --name test1 --network none busybox /bin/sh -c "while true;do sleep 3600;done"
    docker network inspect none //创建这样的容器看到只有本地ip, 使用场景 比如是存密码 不希望外界访问。

    docker run -d --name test1 --network host busybox /bin/sh -c "while true;do sleep 3600;done"//这个容器和主机共享网络命名空间,可能发生端口冲突


复杂案例:
Q: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by ‘NewConnectionError(’<pip._vendor.urllib3.connection.VerifiedHTTPSConnection object at 0x7fe388ab2550>: Failed to establish a new connection: [Errno -3] Temporary failure in name resolution’,)’: /simple/redis/
A: 重启 service docker restart --!

   先启动redis
   docker run -d --name redis redis
   docker run -d --link redis --name flask-redis -e REDIS_HOST=redis flask-redis

   docker exec -it flask-redis /bin/sh   # 命令行访问
   env  # 查看变量
   curl 127.0.0.1:5000  容器内访问

   docker run -d --link redis -p 5000:5000 --name flask-redis -e REDIS_HOST=redis flask-redis
   curl 127.0.0.1:80  本地访问

多机通信:
vxlan协议 虚拟可扩展的局域网。它是一种 overlay 技术,通过三层的网络来搭建虚拟的二层网络。
链接:https://cizixs.com/2017/09/25/vxlan-protocol-introduction/

需要依赖一个etcd 工具
运维之美etcd 链接:https://draveness.me/etcd-introduction

了解overlay 网络的技术在docker的通信:
链接:https://github.com/docker/labs/blob/master/networking/concepts/06-overlay-networks.md

  1. Docker持久化部署与存储
    在容器中的创建的数据 文件,需要保存,需要Volume。
    docker解决方案:
    1. 基于本地文件系统的Volume,可以执行Docker create或Docker run时,-v 参数将主机目录作为容器的数据卷。
    2. 基于plugin的Volume, 支持第三方的存储方案,如NAS, aws

    Volume的类型:
    1.受管理的data Volume,由docker后台自动创建
    2.绑定挂载的Volume, 具体挂在位置可以由用户指定。

    数据持久化:Data Volume
    docker run -d --name mysql1 -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql
    附:通过 docker logs [mysql_image_name|container_name] 查看日志,找到密码,以及相关错误日志信息等
    docker volume ls
    docker volume inspect

    volume 起别名:
    docker run -d -v mysql:/var/lib/mysql --name mysql1 -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql # -v mysql:/var/lib/mysql 分别是volume别名和映射到本地路径

    数据持久化:Bind Mouting
    docker run -v /home/aaa:/root/aaa # 指定本地目录与容器目录关联

    docker run -d -v $(pwd):/usr/share/nginx/html -p 80:80 --name web nginx #当前路径下文件与容器路径下映射 并文件同步
    附:有些场景非常方便文件查看 程序调试

    场景:wordpress网站
    docker run -d --name mysql -v mysql-data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=wordpress mysql
    docker run -d -e WORDPRESS_DB_HOST=mysql:3306 --link mysql -p 8080:80 wordpress
    附:将配置文件复制到 docker容器docker cp IMAGE_ID:/etc/mysql/my.cnf /etc/mysql/conf/

  2. docker-compose
    场景:
    要从Dockerfile build image 或者Dockerhub 拉取image
    要创建多个container
    要管理这些container(启动停止删除)

    Docker Compose “批处理”
    Docker Compose 是一个工具
    可以通过yml文件定义多容器的docker应用
    通过一条命令就可以根据yml文件的定义去创建或管理这么多的容器

    centos中安装docker-compose:
    sudo curl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose

    sudo chmod +x /usr/local/bin/docker-compose

    docker-compose --version
    > docker-compose version 1.22.0, build f46880fe

    docker-compse.yml
    三大概念:Services、Networks、Volumes

    Services:
    一个service代表一个container,这个container可以从dockerhub的image来创建,或者本地的Dockerfile build出来的image来创建
    service的启动类似docker run,可以给其指定network和volume, 所以可以给service指定network和Volume的引用

    services:
        worker:
            build: ./worke
            links:
                - db 
                - redis 
            networks:
                - back-iter                                # 相当于 docker network create -d bridge back-iter
            volumes:
                - "db-data:/var/lib/postgresql/data"       # 相当于 docker volume create db-data
    

    使用:
    docker-compose.yml 文件
    docker-compose up 启用当前的docker-compose.yml文件

    案例:
    flask-hello-world/ 文件下创建 app.py docker-compose.yml Dockerfile 三个文件

    docker-compose.yml内容:

        version: "3"
    
        services:
    
        redis:
            image: redis
    
        web:
            build:
            context: .
            dockerfile: Dockerfile
            ports:
            - 8080:5000
            environment:
            REDIS_HOST: redis
    

    Dockerfile内容:

         FROM qzkc/python2.7:v1
         LABEL maintainer="ccbp"
         RUN pip install flask redis
         COPY . /app/
         WORKDIR /app
         EXPOSE 5000
         CMD ["python","app.py"]
     ```
    

flask app.py 内容如下:

from flask import Flask
import redis
import os
import socket
app = Flask(__name__)
redis = redis.Redis(host=os.environ.get('REDIS_HOST','127.0.0.1'),port=6379)

@app.route('/')
def hello():
    redis.incr('hits')
    return "hello docker I have been seen %s times and my hostname is %s.\n" % (redis.get('hits'),socket.gethostname())

if __name__ == '__main__':
    app.run(host="0.0.0.0",port=5000,debug=True)

负载和扩展规模:

去掉docker-compose.yml 的 ports: ,docker-compose up , docker-compose up --scale web=3 -d ,发现有三个app.py 实现水平扩展web

docker-compose.yml 文件添加:
version: “3”

services:

redis:
    image: redis

web:
    build:
    context: .
    dockerfile: Dockerfile
    environment:
    REDIS_HOST: redis
lb:
    image: dockercloud/haproxy
    links:
    - web
    ports:
    - 8080:80
    volumes:
    - /var/run/docker.sock:/var/run/docker.sock

增加高可用负载均衡代理,再docker-compose ps 查看,web实现了水平扩展。
curl 127.0.0.1:8080 来访问,发现调用了不同的web容器应用。实现了负载均衡

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值