从docker到istio之一:使用Docker将应用容器化

Posted by hiho on November 12, 2020

一、应用准备

1、创建和进入目录 mkdir docker2istio && cd docker2istio

如无特殊说明,下文演示都在docker2istio目录

2、拉去docker

docker pull crunchgeek/php-fpm:7.2

3、在app下编写简单的php脚本。功能简单,收到请求,详情页面访问次数,页面访问次数数据存储到redis中,简单以laravel为例子

composer create-project --prefer-dist laravel/laravel laravelapp "5.*"
cd laravelapp
composer require predis/predis

修改app下的web.php

<?php

use Illuminate\Support\Facades\Redis;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

function getLocalIp()
{

    $isSwoole = (class_exists('Swoole\Coroutine') && method_exists(\Swoole\Coroutine::class, 'getCid') && \Swoole\Coroutine::getCid() > 0);

    $phpUname = php_uname('n');

    if ($isSwoole) {
        $ip = \Swoole\Coroutine\System::gethostbyname($phpUname);
    } else {
        $ip = gethostbyname($phpUname);
    }

    if ($ip && isIp($ip)) {
        return $ip;
    }

    $preg = "/\A((([0-9]?[0-9])|(1[0-9]{2})|(2[0-4][0-9])|(25[0-5]))\.){3}(([0-9]?[0-9])|(1[0-9]{2})|(2[0-4][0-9])|(25[0-5]))\Z/";

    $out = null;
    $stats = false;

    if ($isSwoole) {
        $out = \Swoole\Coroutine\System::exec('ifconfig', $stats);
    } else {
        if (function_exists('exec')) {
            //获取操作系统为linux类型的本机IP真实地址
            exec("ifconfig", $out, $stats);
        }
    }
    if (!empty($out)) {
        if (isset($out[1]) && strstr($out[1], 'addr:')) {
            $tmpArray = explode(":", $out[1]);
            $tmpIp = explode(" ", $tmpArray[1]);
            if (preg_match($preg, trim($tmpIp[0]))) {
                return trim($tmpIp[0]);
            }
        }
    }


    return '127.0.0.1';
}

function isIp(string $str): bool
{
    $ip = explode('.', $str);
    for ($i = 0; $i < count($ip); $i++) {
        if ($ip[$i] > 255) {
            return false;
        }
    }
    return preg_match('/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/', $str) ? true : false;
}

Route::get('/', function () {

    Redis::incr('hits');
    $hits = Redis::get('hits');
    $request = request();
    $clientIp = $request->getClientIp();
    $host = getLocalIp();
    return "Hello World by {$host} from {$clientIp} ! 该页面已被访问 {$hits} 次。\n";
//    return view('welcome');
});

修改app/.env

REDIS_HOST=docker2istio-redis

制作应用镜像

在php应用程序下新建dockerfile文件

vim laravelapp/Dockerfile
FROM php:7.4-cli

COPY . /var/www/html
WORKDIR /var/www/html

EXPOSE 8080

CMD ["php","artisan","serve","--host=0.0.0.0","--port=8080"]


构建应用镜像

cd laravelapp
docker build -f ./laravelapp/Dockerfile -t laravelapp:0.0.1 ./laravelapp

启动容器

创建docker内部的app网络

docker network create -d bridge docker2istio-net

创建docker内部网络,可以让docker的container直接直接连通,不用通过端口暴露本地网络再连通。

然后依次:

1、启动redis

docker run -d --rm --name redis --network docker2istio-net --name docker2istio-redis redis:4-alpine3.8

2、启动app

docker run -d --rm -p 8080:8080 --network docker2istio-net --name docker2istio-app  laravelapp:0.0.1

3、启动nginx

docker run -d --rm --name docker2istio-nginx --network docker2istio-net -p 80:80 -v $PWD/nginx:/etc/nginx/conf.d nginx:1.15.8-alpine

其中nginx的 nginx/default.conf 文件内容如下:

upstream laravelapp {
    server docker2istio-app:8080;
}
server {
    listen       80;
    server_name  localhost;

    root /usr/share/nginx/html;

    location / {
        proxy_pass http://laravelapp;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_redirect off;
    }

}






应用测试

访问 127.0.0.1:80

2.png

先检查一下容器, docker ps 可以看到三个容器 : 3.png

—End—

迭代

  • 2020年11月12日 16:30 初稿

参考