bjw211 / docker_example

docker使用教程

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

简单易懂的docker教程

基本概念

镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的 类 和 实例一样,镜像是静态的定义,容器是镜像运行时的实体,容器可以被创建、启动、停止、删除、暂停等。

常用命令

docker pull pkg:version     # 拉取 image
docker images               # 查看所有 image
docker rmi myphp            # 删除 image
docker ps                   # 查看运行中的 container
docker ps -a                # 查看所有 container
docker inspect myphp        # 查看 container 配置
docker logs myphp           # 查看 container 日志
docker restart myphp        # 重启 container
docker stop myphp           # 停止 container
docker rm myphp             # 删除 container
docker exec -it myphp bash  # 进入到 container 
docker build -t repository_name[:tag_name] Dockerfile_dir # 构建 image
docker volume ls            # 查看数据卷
docker volume prune         # 删除所有数据卷!!!!!!超级危险,生产环境不要执行!!!!!!

Mac使用docker搭建PHP环境

(一阶)使用docker逐一构建

首先创建对应的目录结构

lnmp -|
     -| nginx   -|
                -| conf.d -|
                -| nginx.conf
                -| fastcgi_params
                -| mime.types
              
     -| logs    -|
                -| nginx -|
             
     -| mysql   -|
     
     -| php     -|
     
     -| www     -|
                -| index.php

0. 在网上自己找教程安装docker

1. 下载镜像

docker pull php:7.2-fpm     # 冒号后选择版本

docker pull nginx

docker pull mysql:5.7       # 不需要本地数据库可忽略

docker pull redis:3.2       # 不需要本地redis可忽略

docker images               # 查看已下载的所有镜像

2. 创建容器

==要注意容器的启动顺序==

参数解释:

注:

-i 表示允许我们对容器进行操作

-t 表示在新容器内指定一个为终端

-d 表示容器在后台执行

/bin/bash 这将在容器内启动bash shell

-p 为容器和宿主机创建端口映射

--name 为容器指定一个名字

-v 将容器内路径挂载到宿主机路径

--privileged=true 给容器特权,在挂载目录后容器可以访问目录以下的文件或者目录

--link可以用来链接2个容器,使得源容器(被链接的容器)和接收容器(主动去链接的容器)之间可以互相通信,解除了容器之间通信对容器IP的依赖 
格式:原容器名:设置的别名
在nginx配置文件中,监听php的ip,就可以使用别名,而不使用ip
###### mysql容器

docker run --name mydb -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7

# 注:-MYSQL_ROOT_PASSWORD=123456 给mysql设置初始密码,如果不需要搭建本地数据库直接下一步

###### redis容器

docker run --name myredis -p 6379:6379 -d redis:3.2

# 注: 如果不需要搭建本地redis直接下一步


###### php容器容器

docker run --name myphp -d -p 9000:9000 -e TZ=Asia/Shanghai -v ~/Documents/lnmp/www:/var/www/html -v ~/Documents/lnmp/php:/usr/local/etc/php --link mydb:mydb --link myredis:myredis --privileged=true php:7.2-fpm

# 注: 如果不需要搭建本地数据库或者redis可以省去--link mydb:mydb --link myredis:myredis
#注意-v 挂载一个空文件夹是会覆盖容器中的内容,所以配置文件要事先准备好


###### nginx容器

docker run --name mynginx -d -p 80:80 -e TZ=Asia/Shanghai -v ~/Documents/lnmp/www:/usr/share/nginx/html -v ~/Documents/lnmp/nginx:/etc/nginx -v ~/Documents/lnmp/logs/nginx:/var/log/nginx --link myphp:myphp --privileged=true nginx

#注:
#-v语句冒号后是容器内的路径 我将nginx的网页项目目录 配置目录 日志目录分别挂载到了我事先准备好的~/Documents/lnmp目录下
#--link myphp:myphp 将nginx容器和php容器连接 通过别名myphp就不再#需要去指定myphp容器的ip了 

docker ps -a 查看所有容器运行成功 这里环境也就基本搭建完成了

==此时访问localhost,应该存在很多问题需要排坑,大多是nginx配置问题,接着往下看==

如果有容器创建失败,则可以使用docker logs name 查看日志,按照日志报错解决问题

挂载目录后就可以不用进入容器中修改配置,直接在对应挂载目录下改配置文件 修改nginx配置到 ~/Documents/lnmp/nginx/conf.d/xxx.conf

nginx配置示例

#user  nobody;
worker_processes  1;

#pid        logs/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    server {
        listen       80;
        server_name  localhost;

        location / {
            root /usr/share/nginx/html;
            # 这里是工作目录指定,已经映射到自定义的文件夹
            # 如果入口还在下层,可以在后面加目录,比如:/usr/share/nginx/html/public
            index index.html index.htm index.php;
        }
        
        location ~ \.php$ {
           fastcgi_pass   myphp:9000;
           # 容器与容器之间建立连接必须指定对方的ip,使用命令docker inspect myphp可以看到最现在IPAdress参数就是该容器ip
           # 我们在创建容器时,已经通过 --link 的方式创建容器,我们可以使用被link容器的别名进行访问,而不是通过ip,解除了对ip的依赖
           fastcgi_index  index.php;
           fastcgi_param  SCRIPT_FILENAME /var/www/html/$fastcgi_script_name;
           # myphp和mynginx的工作目录不同,nginx的是/usr/share/nginx/html
           # php的是/var/www/html 所以在创建容器时我们已经将两个目录都挂载到宿主主机相同的目录上了~/Documents/lnmp/www,介在这里不能使用宿主主机公共挂载目录,要使用php的工作目录
           include        fastcgi_params;
        }
    }

    include /etc/nginx/conf.d/*.conf;
}

3. php扩展安装

docker exec -ti myphp /bin/bash      # 首先进入容器

docker-php-ext-install pdo pdo_mysql # 安装pdo_mysql扩展

docker-php-ext-install redis
# 注: 此时报错提示redis.so 因为一些扩展并不包含在 PHP 源码文件中

==解决办法:==

  1. 通过源码安装
tar zxvf /server/php_lib/redis-4.1.0.tgz # 解压已经下载好的redis扩展包

docker cp /server/php_lib/redis-4.1.0 myphp:/usr/src/php/ext/redis # 将扩展放到容器中 再执行安装
注:
直接将扩展包放到容器ext目录里可能会报错Error: No such container:path: myphp:/usr/src/php/ext
你可以多开一个服务器窗口 进入php容器中执行docker-php-ext-install  redis此时报错error: /usr/src/php/ext/redis does not exist
保持这个状态然后在你的第一个服务器窗口执行上条命令就成功了 
(具体原因未知但确实要执行一次docker-php-ext-install命令 容器中才会开放/usr/src/php/ext这个目录)
  1. 通过pecl安装 ==(推荐)==
# 注: 
# 官方推荐使用 PECL(PHP 的扩展库仓库,通过 PEAR 打包)。
# 用 pecl install 安装扩展,然后再用官方提供的 docker-php-ext-enable 
# 快捷脚本来启用扩展

pecl install redis && docker-php-ext-enable redis

docker restart myphp        # 装完扩展 退出容器 重启容器

4. 构建自己的目录结构(直接摘抄)

你也可以构建自己所要的server目录结构 首先要知道挂载一个空文件夹会清空容器中文件夹下所有内容 所以应该先拷贝再挂载
例如: 创建一个临时容器 sudo docker run --name mynginx -p 80:80 -it -d nginx
进入到容器中查自己所要的配置文件目录地址 例如: /etc/nginx 退出容器 
拷贝容器中所要的目录结构到宿主机 例如: docker cp mydb:/etc/nginx /server/nginx
删除容器 创建新容器时就可以挂载该目录了 此后对nginx的配置文件的修改就可以直接在宿主机上快捷操作
docker run --name mynginx -d -p 80:80 -v /server/nginx:/etc/nginx --link myphp:myphp --privileged=true  nginx

(二阶)使用docker-compose自动化构建

完成以上步骤你就已经初步了解了docker的基本容器操作
docker-compose是编排容器的。例如,你有一个php镜像,一个mysql镜像,一个nginx镜像。如果没有docker-compose,
那么每次启动的时候,你需要敲各个容器的启动参数,环境变量,容器命名,指定不同容器的链接参数等等一系列的操作,
相当繁琐。而用了docker-composer之后,你就可以把这些命令一次性写在docker-composer.yml文件中,以后每次启动
这一整个环境(含3个容器)的时候,你只要敲一个docker-composer up命令就ok了

1. 安装docker-compose

mac中不用执行这一步,安装docker默认已经安装完docker-compose

curl -L https://github.com/docker/compose/releases/download/1.8.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose

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

docker-compose --version

2. 一键部署环境

进入到docker-compose.yml目录下,执行docker-compose up -d,后台开启容器

3. docker-compose.yml配置参考

==docker-compose的语法建议查看官方文档==

version: "2"
services:
  mydb:
    image: mysql:5.7    # 容器的引用镜像
    container_name: "mydb" # 容器命名
    restart: always
    ports:
      - "3306:3306"
    volumes:    # 挂载目录写这里(也可以写相对路径)
      - ~/Documents/lnmp/mysql:/var/lib/mysql
    environment:    # 自定义环境变量
      MYSQL_ROOT_PASSWORD: 123456
      TZ: Asia/Shanghai   # 时区

  myredis:
    image: redis:3.2
    container_name: "myredis"
    restart: always
    ports:
      - "6379:6379"
    volumes:
      - ~/Documents/lnmp/redis:/data
    environment:
        TZ: Asia/Shanghai

  myphp:
    image: php:7.2-fpm
    container_name: "myphp"
    restart: alwaysr
    ports:
      - "9000:9000"
    volumes:
      - ~/Documents/lnmp/www:/var/www/html
      - ~/Documents/lnmp/php:/usr/local/etc/php
    links:
      - "mydb"
      - "myredis"
    environment:
        TZ: Asia/Shanghai

  mynginx:
    image: nginx:latest
    container_name: "mynginx"
    restart: always
    ports:
      - "80:80"
    volumes:
      - ~/Documents/lnmp/www:/usr/share/nginx/html
      - ~/Documents/lnmp/nginx:/etc/nginx
      - ~/Documents/lnmp/logs/nginx:/var/log/nginx
    links:
      - "myphp"
    environment:
        TZ: Asia/Shanghai

对比上面运行容器命令来看docker_yml的配置结构和语义就一目了然了

(三阶)dokcer-compose和dockerfile 完整构建

用了docker-compose实现一键式操作,但问题是PHP的扩展库还是得自己单独装 所以这里需要用到Dockerfile来构建自定义容器镜像实现真正的一键完成

1. 完善目录结构

docker  -|
        -| dockerfiles  -|
                        -| docker-compose.yml
                        
                        -| mount -|
                                 -| conf -|
                                         -| php.ini
                                         -| nginx.conf
                                         -| my.cnf
                                         -| vhost.conf
                                         -| mime.types
                                         
                                 -| data -|
                                         -| mysql -|
                                         -| redis -|
                                 
                                 -| logs -|
                                         -| nginx -|
                                 
                        -| mysql -|
                                 -| Dockerfile
                                 
                        -| nginx -|
                                 -| Dockerfile
                                 
                        -| php   -|
                                 -| Dockerfile
                                 
                        -| redis -|
                                 -| Dockerfile
                        
        -| website  -|
                -| index.php
                -| index.html

2. php Dockerfile 示例

在这里只展示php的Dockerfile,因为最复杂的就是PHP的镜像,其他配置详情可以在github中查看

FROM php:7.2-fpm

# 按需安装php扩展
# 1.0.2 增加 bcmath, calendar, exif, gettext, sockets, dba, 
# mysqli, pcntl, pdo_mysql, shmop, sysvmsg, sysvsem, sysvshm 扩展
RUN docker-php-ext-install -j$(nproc) bcmath calendar exif gettext \
sockets dba mysqli pcntl pdo_mysql shmop sysvmsg sysvsem sysvshm

# 1.0.7 增加 soap 扩展
RUN apt-get update && \
	apt-get install -y --no-install-recommends \ 
	libxml2-dev libtidy-dev libxslt1-dev zlib1g-dev \ 
	&& rm -r /var/lib/apt/lists/* \ 
	&& docker-php-ext-install -j$(nproc) soap
    
# 使用pecl安装扩展,记得在php.ini中添加配置项(grpc依赖于zlib1g-dev扩展)
RUN pecl install grpc-1.22.1 \
	&& pecl install swoole-4.4.4 \
	&& docker-php-ext-enable grpc swoole

# 如果扩展下载时间太长,可以先下载到本地,再copy到指定目录,再用pecl安装
COPY ./redis-4.0.1.tgz /home/redis.tgz
COPY ./xdebug-2.6.0.tgz /home/xdebug.tgz
RUN pecl install /home/redis.tgz \
    && pecl install /home/xdebug.tgz \
    && docker-php-ext-enable redis xdebug

# 安装composer(compoaer.phar需要先下载到本地)
ADD composer.phar /usr/local/bin/composer
RUN chmod 755 /usr/local/bin/composer

注意:

自定义php的dockerfile构建自定义镜像同时安装扩展 完成了所有dockerfile配置后 docker-compose.yml文件就不需要 再用官方镜像image:php-fpm:7.2 而是直接==build:./php== 直接引用目录配置好的Dockerfile

最后提示: 镜像一旦创建了下次docker-compose会直接取已有镜像而不会build创建 若你修改了Dockerfile配置请记得删除之前镜像并重新构建

3. docker-compose.yml 示例

version: "2"
services:
  mysql:
    build: ./mysql # 这里换成了从Dockerfile文件构建
    image: dev-mysql # 为构建的image命名 repository_name:tag_name(可选)
    container_name: dev-mysql # 创建容器时的名称
    ports:
      - "3306:3306"
    volumes: # 挂载目录写这里
      - ./mount/data/mysql:/var/lib/mysql
      - ./mount/conf/my.cnf:/etc/mysql/conf.d/my.cnf
    environment: # 自定义环境变量
      MYSQL_ROOT_PASSWORD: 123456
      TZ: Asia/Shanghai

  redis:
    build: ./redis
    image: dev-redis
    container_name: dev-redis
    ports:
      - "6379:6379"
    volumes:
      - ./mount/data/redis:/data
    environment:
        TZ: Asia/Shanghai

  php:
    build: ./php
    image: dev-php
    container_name: dev-php
    ports:
      - "9000:9000"
    volumes:
      - ../website:/var/www/html
      - ./mount/conf/php.ini:/usr/local/etc/php/php.ini
    links:
      - "mysql" # service名称
      - "redis"
    environment:
        TZ: Asia/Shanghai

  nginx:
    build: ./nginx
    image: dev-nginx
    container_name: dev-nginx
    ports:
      - "80:80"
    volumes:
      - ../website:/usr/share/nginx/html
      - ./mount/conf/nginx.conf:/etc/nginx/nginx.conf
      - ./mount/conf/vhosts.conf:/etc/nginx/conf.d/default.conf
      - ./mount/logs/nginx:/var/log/nginx
    links:
      - "php"
    environment:
        TZ: Asia/Shanghai

Dockerfile 和 docker-compose.yml配置好之后,执行 docker-compose up --build 构建并启动

也可以执行 docker-compose build 先构建,再使用下面的命令启动

首次构建之后,以后启动可以使用 docker-compose up -d 后台启动

常见问题

1. 在宿主主机执行php容器cli命令

docker exec -it dev-php bash -c 'composer --version'

也可以直接使用 docker exec -it dev-php bash 进入容器,再执行命令

参考链接

docker灵活的构建php环境 https://github.com/ydtg1993/server

docker-compose.yml 语法解析 https://deepzz.com/post/docker-compose-file.html

php:7.2-fpm 扩展配置 https://www.jianshu.com/p/20fcca06e27e

Docker在PHP项目开发环境中的应用 http://avnpc.com/pages/build-php-develop-env-by-docker

Docker — 从入门到实践 https://yeasy.gitbooks.io/docker_practice/content/

Docker Reference https://docs.docker.com/reference/

Docker Store https://store.docker.com/

About

docker使用教程


Languages

Language:Dockerfile 65.5%Language:HTML 33.6%Language:PHP 0.9%