Docker应用实践&一些使用技巧

2022-08-21  本文已影响0人  gao922699

使用docker的理由:

  1. 不污染主系统就可以使用众多Linux程序(替代虚拟化技术)

  2. 保证项目运行环境一致(运行环境可加入版本控制,做成镜像更容易重复使用)

  3. 保证项目各个部分在一个封闭的空间内,不受外交干扰(微服务化)

开发中的使用技巧

OVERRIDE文件的使用

docker-compose.override.yml文件里的内容会覆盖docker-compose.yml的内容,可以在里面定义本地环境自有的属性,还可以在里面添加service,这样本地的服务也可以使用同一个网络环境了。比如原docker-compose里没有mysql服务,可以在override里面加一个,还比如一些需要绑定本地目录的由于本地路径无法确定,需要写在override里面;如果一组service里面你只想启用部分,可以在override中用image:hello-world;entrypoint:[true]来覆盖不想启动的service

使用npm环境编译vue项目

docker run -it -d -v:~/code:/www -w /www node bash

exec进入容器后就可以使用npm命令了

删除名称为none的镜像

docker rmi $(docker images | grep "none" | awk '{print $3}')

docker run 的时候加上--rm可以避免生成名称为none的镜像

固定容器IP

每个docker-compose启动的时候会生成一个名称为default的network,通过配置network可以固化容器的IP

例:php代码里面要调用www.site1.com这个站点的服务,这个站点运行在nginx服务下,需要配置hosts才能访问;如果不固化ip,每次重启服务都可能引起nginx服务IP变化,导致hosts实效。固化IP的方法如下:

version: '3'

services:
  nginx:
    networks:
      default:
        ipv4_address: 172.20.1.13
    depends_on:
      - php
  php:
    extra_hosts:
      - "www.site1.com:172.20.1.13"
    networks:
      default:
        ipv4_address: 172.20.1.14
networks:
  default:
    ipam:
      config:
        - subnet: 172.20.1.0/24

注意:这里固定的ip只是SERVER_IP,REMOTE_ADDR获取到的是网关的IP

address不能设为.1,.1默认被网关占用了

访问宿主机的服务

一般推荐需要相互访问的服务写在一个docker-compose中,这样这些服务是在同一个网络中的可以直接访问。如果实在要访问不同的容器提供的服务,通过暴露端口绑定宿主机端口来实现。!!注意宿主机的防火墙设置!!容器中是可以访问宿主机的本地IP+端口的。

建本地私有仓库

registry 官方开源的仓库代码

https://www.jianshu.com/p/fef890c4d1c2

项目部署实践和遇到的问题

项目部署推荐使用docker-compose编排容器。

  1. 项目代码目录权限问题

    使用volume方式绑定的项目文件会存在权限问题(项目文件在容器内可能没有执行权限)

    解决方式:通过dockerfile的COPY命令把项目文件拷贝到容器内,拷贝进去的文件默认是root权限,COPY命令也有 --chown 参数可以设置文件权限,但仅支持linux下。也可以在dockerfile内通过chown、chmod命令给文件授权;COPY和ADD的区别。推荐使用COPY

  2. 上下文(context)概念

  3. https://www.cnblogs.com/jiangzhaowei/p/10055425.html

  4. 多个服务部署同一台机器的问题

    宿主机起一个nginx服务,docker的nginx服务映射到本地的非80端口,然后通过宿主机的nginx的proxy服务转发到docker内nginx服务绑定的本地端口上。

  5. 生产环境和和测试环境不用env文件的维护

    部署的项目在git上使用dev,release分支来区分env文件,见下面的例子,不同分支上的env文件是不一样的。

目前项目中遇到的相对最复杂的docker-compose案例

image.png

docker-compose.yml文件:

version: '3'

services:
  nginx:
    image: nginx:latest
    tty: true
    volumes://项目代码放在同级目录中
      - ../site-group/nginx.template:/etc/nginx/conf.d/nginx.template:ro 
      - ../site-group:/www:ro
    environment:
      - ADMIN_HOST=site-group.local
    command: ["bash", "/www/nginx-up.sh"] //替换nginx.template中的ADMIN_HOST环境变量的脚本
    depends_on:  //效果是先启动php再启动nginx
      - php
  php:
    build:  //生产环境用Dockerfile中的ADD命令来添加项目代码,可以解决文件权限问题,
               开发环境可以直接在下面volumes中绑定项目代码,然后手动修改权限(ADD要时间)
      context: ../site-group
      dockerfile: Dockerfile
    tty: true
    working_dir: /www
    volumes:
      - ./site-group/.env:/www/.env   //使用目录中的env文件替换项目中的env文件
    command: ["bash", "/www/php-up.sh"]  //项目启动时运行的脚本
  mysql:
    image: mysql:5.7.22
    environment:
      - MYSQL_ROOT_PASSWORD=root
  site-group-spider:
    build:  //一个python程序,从dockerfile构建
      context: ../site-group-spider
      dockerfile: Dockerfile
    volumes:
      - ../site-group-spider:/app
      - ./site-group-spider/config.py:/app/config.py  //替换配置文件
    tty: true
    entrypoint: ["python", "/app/spider/spider.py"]  //替换entrypoint

docker-compose.override.yml文件:

version: '3'

services:
  out-nginx:  //外层的nginx服务,用来模拟宿主机的nginx服务
    image: nginx:latest
    volumes:
      - ../site-group/out_admin_nginx.conf:/etc/nginx/conf.d/default.conf
      - ../site-group/out_nginx.conf:/etc/nginx/conf.d/out_nginx.conf
      - ../site-group/inotify:/www/inotify
    ports:
      - "80:80"
    depends_on:
      - php
      - nginx
    networks:
      default:
        ipv4_address: 172.20.1.11  //固化容器IP
  site-group-spider:
    image: hello-world
    entrypoint: ["true"]
    networks:
      default:
        ipv4_address: 172.20.1.12
  nginx:
    ports:
      - "8881:80"
    environment:  //替换env变量为本地值
      - ADMIN_HOST=www.site-group.com
    networks:
      default:
        ipv4_address: 172.20.1.13
    depends_on:
      - php
  mysql:
    ports:
      - "3306:3306"
    volumes:
      - ~/docker/mysql/backup:/backup
      - ~/docker/mysql/data:/var/lib/mysql
  php:
    extra_hosts:  //配置hosts,因为php服务中要调用nginx服务提供的站点,不配置hosts无法访问到
      - "www.site1.com:172.20.1.13"
    networks:
      default:
        ipv4_address: 172.20.1.14
networks:
  default:
    ipam:
      config:
        - subnet: 172.20.1.0/24

site-group项目中的文件:

Dockerfile:

FROM panwenbin/php-fpm-7.1-laravel-centos

ADD . /www  //使用ADD方式添加项目代码到容器内

WORKDIR /www

RUN composer install --no-dev \      //执行安装vendor目录
  && chown -R apache:apache /www        //修改项目目录所有者,和php服务用户一致,就可以解决权限问题

EXPOSE 9000

nginx.template:nginx容器使用的配置文件模板

server {
    listen       80;

    server_name _;  //不限制域名

    client_max_body_size 100m;

    root   /www/public;
    index  index.html index.php index.htm;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    #根据域名生成数据表前缀
    if ( $host ~ ^www\.(\w+)\.(\w+)$ ) {
        set $prefix $1_$2_;
    }

    if ( $host ~ ^www\.(\w+)\.(\w+)\.(\w+)$ ) {
        set $prefix $1_$2_$3_;
    }

    if ( $host != '${ADMIN_HOST}' ) {    //此处的环境变量为docker-compose文件中配置的值
        set $dbPrefix $prefix;
    }

    error_page 404 /index.php;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    location ~ \.php$ {
        fastcgi_pass   php:9000;  //php服务名称和暴露的端口
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
        fastcgi_send_timeout 300;
        fastcgi_read_timeout 300;
        fastcgi_param DB_PREFIX $dbPrefix;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }

}

nginx-up.sh:替换环境变量的脚本

#!/bin/bash
envsubst '${ADMIN_HOST}' < /etc/nginx/conf.d/nginx.template > /etc/nginx/conf.d/default.conf && exec nginx -g 'daemon off;'

out_admin_nginx_conf.example:外部(宿主机)nginx服务使用的nginx配置,做了一层转发到内部的nginx服务,按注释要求修改后使用

server {
    listen 80;
    #系统后台域名
    server_name site-group.com;
    return 301 http://www.$host$request_uri;
}

server {
    listen 80;
    #系统后台www域名
    server_name www.site-group.com;
    location = / {
        rewrite / /admin redirect;
    }
    location / {
        #转发到内部的nginx开放的端口
        proxy_pass    //本机IP+暴露端口 
        proxy_set_header Host $host;
    }
}

out_nginx_conf.example:同上

server {
    listen 80;
    #路径替换为项目路径
    include /www/inotify/nginx_server_names.conf;  //inotify文件中生成的存放servername的文件,通过inotify服务监听自动重启外层的nginx服务
    return 301 http://www.$host$request_uri;
}

server {
    listen 80;
    #路径替换为项目路径
    include /www/inotify/nginx_www_server_names.conf;
    location / {
        #转发到docker的nginx开放的端口
        proxy_pass http://192.168.2.75:8881;
        proxy_set_header Host $host;
    }
}

php-up.sh

#!/bin/bash
php artisan nginx:up-servernames && php-fpm -F
上一篇下一篇

猜你喜欢

热点阅读