Yii2 教程 - yii2-redis 扩展详解

该教程已被合并到《Yii2 权威指南中文版》中!Yiichina 教程地址为《yii2-redis 扩展详解》!

一、简介

yii2-redis 扩展为 Yii2 框架提供了 redis 键值存储支持。包括缓存(Cache)、会话存储处理(Session),并实现了 ActiveRecord 模式,允许您将活动记录存储在 redis 中。

相关链接

二、安装扩展

在 Yii2 项目根目录,执行以下命令安装:

$ composer require yiisoft/yii2-redis

也可以先在 composer.json 文件中声明如下依赖:

"yiisoft/yii2-redis": "~2.0.0"

再执行下面命令安装:

$ composer update

三、基本使用

继续阅读请确保已安装并开启了 redis 服务,安装请参考《Redis 安装》

1. 配置

在组件中添加如下配置:

'components' => [
    'redis' => [
        'class' => 'yii\redis\Connection',
        'hostname' => 'localhost',
        'port' => 6379,
        'database' => 0,
    ],
]  

2. 示例

下面代码演示了 redis 最基本的 string 类型的使用:

// 获取 redis 组件
$redis = Yii::$app->redis;

// 判断 key 为 username 的是否有值,有则打印,没有则赋值
$key = 'username';
if ($val = $redis->get($key);) {
    var_dump($val);
} else {
    $redis->set($key, 'marko');
    $redis->expire($key, 5);
}

这个类中(yii\redis\Connection)提供了操作 redis 所有的数据类型和服务(String、Hash、List、Set、SortedSet、HyperLogLog、GEO、Pub/Sub、Transaction、Script、Connection、Server)所需要的方法,并且和 redis 中的方法同名,如果不清楚可以直接到该类中查看。

四、缓存组件

该扩展中的 yii\redis\Cache 实现了 Yii2 中的缓存相关接口,所以我们也可以用 redis 来存储缓存,且用法和原来一样。

1. 配置

修改组件中 cache 的 class 为 yii\redis\Cache 即可,配置如下:

'components' => [
    'cache' => [
        // 'class' => 'yii\caching\FileCache',
        'class' => 'yii\redis\Cache',
    ],
],

如果没有配置过 redis 组件,需要在 cache 组件下配置 redis 服务相关参数,完整配置如下:

'components' => [
    'cache' => [
        // 'class' => 'yii\caching\FileCache',
        'class' => 'yii\redis\Cache',
        'redis' => [
            'hostname' => 'localhost',
            'port' => 6379,
            'database' => 0,
        ],
    ],
],

2. 示例

下面代码演示了缓存的基本使用:

// 获取 cache 组件
$cache = Yii::$app->cache;

// 判断 key 为 username 的缓存是否存在,有则打印,没有则赋值
$key = 'username';
if ($cache->exists($key)) {
    var_dump($cache->get($key));
} else {
    $cache->set($key, 'marko', 60);
}

使用文件缓存(FileCache)时,缓存是存储在 runtime/cache 目录下;使用 redis 缓存后,缓存将存储在 redis 数据库中,性能将大大提高。

五、会话组件

该扩展中的 yii\redis\Session 实现了 Yii2 中的会话相关接口,所以我们也可以用 redis 来存储会话信息,且用法和原来一样。

1. 配置

修改组件 session 的配置,指定 class 为 yii\redis\Session 即可,配置如下:

'components' => [
    'session' => [
        'name' => 'advanced-frontend',
        'class' => 'yii\redis\Session'
    ],
],

如果没有配置过 redis 组件,需要在 session 组件下配置 redis 服务相关参数,完整配置如下:

'components' => [
    'session' => [
        'name' => 'advanced-frontend',
        'class' => 'yii\redis\Session',
        'redis' => [
            'hostname' => 'localhost',
            'port' => 6379,
            'database' => 0,
        ],
    ],
],

2. 使用

在开发过程中,切记一定不要使用 PHP 原生的 $_SESSION 去操作,而要使用 Yii 提供的 session 组件,获取方式如下:

$session = Yii::$app->session;

六、ActiveRecord

该扩展中的 yii\redis\ActiveRecord 实现了 Yii2 中的 ActiveRecord 相关接口,所以我们可以使用 AR 的方式操作 redis 数据库。关于如何使用 Yii 的 ActiveRecord,请阅读权威指南中有关 ActiveRecord 的基础文档。

定义 redis ActiveRecord 类,我们的模型需要继承 yii\redis\ActiveRecord,并至少实现 attributes() 方法来定义模型的属性。

主键可以通过 yii\redis\ActiveRecord::primaryKey() 定义,如果未指定,则默认为 id。 primaryKey 必须在 attributes() 方法定义的属性中,如果没有指定主键,请确保 id 在属性中。

下面定义一个 Customer 模型来演示:

class Customer extends \yii\redis\ActiveRecord
{
    /**
     * 主键 默认为 id
     *
     * @return array|string[]
     */
    public static function primaryKey()
    {
        return ['id'];
    }

    /**
     * 模型对应记录的属性列表
     *
     * @return array
     */
    public function attributes()
    {
        return ['id', 'name', 'age', 'phone', 'status', 'created_at', 'updated_at'];
    }

    /**
     * 定义和其它模型的关系
     *
     * @return \yii\db\ActiveQueryInterface
     */
    public function getOrders()
    {
         return $this->hasMany(Order::className(), ['customer_id' => 'id']);
    }

}

使用示例:

// 使用 AR 方式新增一条记录
$customer = new Customer();
$customer->name = 'marko';
$customer->age = 18;
$customer->phone = 13888888888;
$customer->status = 1;
$customer->save();
echo $customer->id;

// 使用 AR 查询
$customer = Customer::findOne($customer->id);
$customer = Customer::find()->where(['status' => 1])->all();

redis ActiveRecord 的一般用法与权威指南中数据库的 ActiveRecord 用法非常相似。它们支持相同的接口和方法,除了以下限制:

  • 由于 redis 不支持 sql,查询方法仅限于使用以下方法:where(),limit(),offset(),orderBy() 和 indexBy()。 【 orderBy() 尚未实现:#1305)】
  • 由于 redis 没有表的概念,因此不能通过表定义关联关系,只能通过其它记录来定义关系。

七、直接使用命令

直接使用 redis 连接,就可以使用 redis 提供的很多有用的命令。配置好 redis 后,用以下方式获取 redis 组件:

$redis = Yii::$app->redis;

然后就可以执行命令了,最通用的方法是使用 executeCommand 方法:

$result = $redis->executeCommand('hmset', ['test_collection', 'key1', 'val1', 'key2', 'val2']);

支持的每个命令都有一些快捷方式,可以按照如下方式使用:

$result = $redis->hmset('test_collection', 'key1', 'val1', 'key2', 'val2');

有关可用命令及其参数的列表,请参阅 redis 命令:


本文首发于马燕龙个人博客,欢迎分享,转载请标明出处。
马燕龙个人博客:https://www.mayanlong.com
马燕龙个人微博:http://weibo.com/imayanlong
马燕龙Github主页:https://github.com/yanlongma

PHP 基础篇 - PHP 正则官方文档汇总

一、PCRE 正则语法

下面是 PHP 的 PCRE 正则语法(模式语法)相关文档,详情请查阅相关链接:

二、PCRE 模式修饰符

下面列出了当前可用的 PCRE 修饰符,详情请看官方文档

  • i (PCRE_CASELESS)
  • m (PCRE_MULTILINE)
  • s (PCRE_DOTALL)
  • x (PCRE_EXTENDED)
  • e (PREG_REPLACE_EVAL)
  • A (PCRE_ANCHORED)
  • D (PCRE_DOLLAR_ENDONLY)
  • S
  • U (PCRE_UNGREEDY)
  • X (PCRE_EXTRA)
  • J (PCRE_INFO_JCHANGED)
  • u (PCRE_UTF8)

三、PCRE 函数

下面是 PHP 的 PCRE 函数相关文档,详情请查阅相关链接:


本文首发于马燕龙个人博客,欢迎分享,转载请标明出处。
马燕龙个人博客:https://www.mayanlong.com
马燕龙个人微博:http://weibo.com/imayanlong
马燕龙Github主页:https://github.com/yanlongma

PHP 基础篇 - PHP 错误级别详解

一、前言

最近经常看到工作 2 年左右的童鞋写的代码也会出现以静态方法的形式调用非静态方法,这是个 Deprecated 级别的语法错误,代码里不应该出现的。对方很郁闷,说:为什么我的环境可以正常运行呢?

二、详解

代码会不会报错,以及你能不能看到报错信息由 PHP 配置中以下两个参数影响,目前线上主流的配置如下(php.ini 文件中):

error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
display_errors = Off

下面详细介绍这两个参数:

1. error_reporting

首先来说说 PHP 的错误级别,代码会不会报错由 error_reporting 参数决定,PHP 的错误级别种类如下(点击查看中文版):

E_ALL             - All errors and warnings (includes E_STRICT as of PHP 5.4.0)
E_ERROR           - fatal run-time errors
E_RECOVERABLE_ERROR  - almost fatal run-time errors
E_WARNING         - run-time warnings (non-fatal errors)
E_PARSE           - compile-time parse errors
E_NOTICE          - run-time notices (these are warnings which often result
                    from a bug in your code, but it's possible that it was
                    intentional (e.g., using an uninitialized variable and
                    relying on the fact it is automatically initialized to an
                    empty string)
E_STRICT          - run-time notices, enable to have PHP suggest changes
                    to your code which will ensure the best interoperability
                    and forward compatibility of your code
E_CORE_ERROR      - fatal errors that occur during PHP's initial startup
E_CORE_WARNING    - warnings (non-fatal errors) that occur during PHP's
                    initial startup
E_COMPILE_ERROR   - fatal compile-time errors
E_COMPILE_WARNING - compile-time warnings (non-fatal errors)
E_USER_ERROR      - user-generated error message
E_USER_WARNING    - user-generated warning message
E_USER_NOTICE     - user-generated notice message
E_DEPRECATED      - warn about code that will not work in future versions
                    of PHP
E_USER_DEPRECATED - user-generated deprecation warnings 

其中 WARNING、NOTICE、DEPRECATED 等错误级别会抛出一个错误,但不会终止程序运行。

2. display_errors

再来看一下 display_errors 参数,该参数是是否展示错误信息,只有开启才会显示错误信息(值可以为 on|off、true|false、1|0)。

开发环境最好设置为开启,尽早发现问题,但生产环境一定要关闭。(点击查看中文版官方文档

3. 问题演示

下面使用 PHP 的运行时配置,改变 PHP 的 error_reporting 和 display_errors,演示上面的问题。代码如下:

<?php

// error_reporting(E_ALL & ~E_DEPRECATED & ~E_STRICT);  // 该级别下面的代码不会抛出错误
error_reporting(E_ALL & ~E_NOTICE);
ini_set("display_errors", "on");

class Foo
{
    public function test()
    {
        echo 'test';
    }
}

Foo::test();

运行该代码会输出 test,但同时会抛出一个 Deprecated 级别的错误。这种情况应该杜绝,规范开发,从基础做起,人人有责!


本文首发于马燕龙个人博客,欢迎分享,转载请标明出处。
马燕龙个人博客:https://www.mayanlong.com
马燕龙个人微博:http://weibo.com/imayanlong
马燕龙Github主页:https://github.com/yanlongma

PHP 基础篇 - PHP 的 BC MATH 系列数学函数

一、常见问题

用 PHP 做计算时经常会遇到精度带来的问题,下面来看两个常见的例子:

1. 运算比较

下面表达式输出的结果不是相等

<?php 

echo 2.01 - 0.01 == 2 ? '相等' : '不相等';  // 不相等

2. 类型转换

下面表达式输出的结果不是201(如果想输出你想要的结果,需要先转 string 再转 int):

<?php

$num = intval(2.01 * 100);
var_dump($num);    // int(200)

你也许会觉得很奇怪,然而这并不是 PHP 的 bug,如果想深入了解可以参考鸟哥的两篇文章:

  1. 关于PHP浮点数你应该知道的(All ‘bogus’ about the float in PHP)
  2. PHP浮点数的一个常见问题的解答

二、BC MATH

用 PHP 提供的 BC MATH 系列数学函数可以解决上面的问题。对于任意精度的数学计算, BC MATH 提供了支持用字符串表示的任意大小和精度的数字的二进制计算,最多为2147483647-1(或0x7FFFFFFF-1)。

下面用 BC MATH 提供的函数解决上面的问题。

1. 运算比较

bccomp — 比较两个任意精度的数字:

<?php

$num = bccomp(2.01 - 0.01, 2, 2);   
var_dump($num); // int(0)

注:如果两个数相等返回 0, 左边的数比较右边的数大返回 1, 否则返回-1。

2. 类型转换

bcmul — 2个任意精度数字乘法计算:

<?php

$num = bcmul(2.01, 100, 0);
var_dump($num);    // string(3) "201"
var_dump(intval($num));    // int(201)

注:返回结果为字符串类型

使用 BC MATH 系列数学函数可以让我们减少失误,避免不必要的错误,如需查看详细参数和其它函数的使用,请查阅 PHP 官方文档:http://php.net/manual/zh/book.bc.php


本文首发于马燕龙个人博客,欢迎分享,转载请标明出处。
马燕龙个人博客:https://www.mayanlong.com
马燕龙个人微博:http://weibo.com/imayanlong
马燕龙Github主页:https://github.com/yanlongma

Docker 学习笔记 - 使用 LaraDock 搭建 PHP 开发环境

一、简介

LaraDock 致力于简化创建开发环境过程,能够帮助我们在 Docker 上快速搭建 PHP 开发环境。 它预装了 Docker 镜像,为我们提供了一站式的开发环境,而不需要再去在本地机器安装 PHP、Nginx、MySQL 以及其他任何开发过程中需要的软件。

相关资料:

LaraDock 官网:http://laradock.io
LaraDock Github:https://github.com/LaraDock/laradock

二、安装

请确保已安装Docker,LaraDock 镜像的原理先不介绍,直接进入安装步骤。

1. 建立工作目录

新建 webroot 目录,laradock 和项目的代码都将放在该目录下(也可以直接使用以前的 web 根目录):

$ mkdir webroot

2. 克隆 LaraDock 代码

进入 webroot 目录,执行以下命令:

$ git clone https://github.com/Laradock/laradock.git

3. 生成 LaraDock 配置文件

进入 laradock 目录,执行以下命令:

$ cp env-example .env

如需配置 Nginx 端口、Mysql 密码等,均在 .env 文件中设置即可。

4. 开启容器

在 laradock 目录下执行以下命令,可以选择自己需要启动的容器:

$ docker-compose up -d nginx mysql redis

LaraDock 提供了很多容器,可以根据自己的选择启动。具体如下:

nginx, hhvm, php-fpm, mysql, redis, postgres, mariadb, neo4j, mongo, apache2, caddy, memcached, beanstalkd, beanstalkd-console, workspace

5. 访问 web 服务

在浏览器中访问 http://localhost,发现已经可以访问 nginx 服务,只不过报 404 而已。

三、详解

1. 404 解决方法

打开 laradock/nginx/sites/default.conf,发现 root 为 /var/www/public。在不改配置文件的情况下,只需在 webroot 目录下新建 public/index.html 文件, http://localhost即可正常访问。

2. 数据卷

通过 docker-compose.yml 文件可以看到, webroot/ 目录被映射到 workspace 容器内 /var/www 下作为数据卷。

applications:
  image: tianon/true
  volumes:
    - ${APPLICATION}:/var/www        

3. Nginx 配置虚拟主机

laradock/nginx/sites/ 目录下新建 test.conf,内容如下:

server {

    listen 80;
    listen [::]:80;

    server_name test.com;
    root /var/www/test;
    index index.php index.html index.htm;

}

webroot 目录下新建 test/index.php 文件

hosts 文件中做域名映射 127.0.0.1 test.com (docker-machine ip)

停止、构建、重启容器,在 laradock 目录下执行以下命令即可:

$ docker-compose down
$ docker-compose build nginx
$ docker-compose up -d nginx mysql redis

访问 test.com

Docker 学习笔记 - 使用 Dockerfile 创建镜像

一、概念

Dockerfile 是一种文件格式的配置文件,用户可以使用 Dockerfile 来快速创建自己的镜像。

二、示例

Dockerfile 由一行行命令语句组成,并支持以 # 开头的注释行。一般而言,Dockerfile 分为四个部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令。

下面演示基于 ubuntu 镜像创建 nginx 镜像。

1. 准备 Dockerfile 和所需文件

新建目录 nginx,在该目录下新建 index.html 文件,内容为 Hello Docker!;在该目录下新建 Dockerfile 文件,内容如下:

# 基于 ubuntu 镜像
FROM ubuntu

# 维护者是 myl
MAINTAINER myl

# 安装 nginx,并设置默认 index.html 文件
RUN apt-get update
RUN apt-get install -y nginx
COPY index.html /var/www/html

# 指定镜像的默认入口
ENTRYPOINT ["/usr/sbin/nginx", "-g", "daemon off;"]

# 暴露 80 端口
EXPOSE 80

2. 生成镜像

在 nginx 目录下执行以下命令生成镜像 yanlongma/nginx

$ docker build -t yanlongma/nginx .
$ docker images
REPOSITORY                        TAG                 IMAGE ID            CREATED             SIZE
yanlongma/nginx                   latest              e79f65bd053f        24 minutes ago      216MB

成功生成镜像后,使用 docker images 即可查看到。

3. 运行镜像

使用 Dockerfile 生成的镜像和其它镜像一样使用,下面使用刚刚生成的 yanlongma/nginx 镜像启动一个容器:

$ docker run -d -p 8080:80 yanlongma/nginx
564e7509ff45416f3c99653dc79403ba4e66fdb4b078ae27de824877429f4cdc
$
$ curl http://localhost:8080
hello docker!

容器启动成功后,访问 http://localhost:8080 即可出现我们设置的 index.html 页面中内容。


本文为博主学习笔记,首发于马燕龙个人博客,欢迎分享,转载请标明出处。
马燕龙个人博客:https://www.mayanlong.com
马燕龙个人微博:http://weibo.com/imayanlong
马燕龙Github主页:https://github.com/yanlongma

Docker 学习笔记 - 端口映射与容器互联

一、前言

在实际应用中,经常会碰到需要多个服务组件容器共同协作的情况,这往往需要多个容器之间有能够互相访问到对方的服务。

除了通过网络访问外,Docker 还提供了两个很方便的功能来满足服务访问的基本需求:

  1. 端口映射:允许映射容器内应用的服务端口到本地宿主主机;
  2. 容器互联:提供了互联机制实现多个容器间通过容器名来快速访问。

二、端口映射

Docker 端口映射即映射容器内应用的服务端口到本机宿主机器。

当容器中运行一些网络应用,要让外部访问这些应用时,可以通过 -P 或 -p 参数两种方式来指定端口映射。

1. 随机映射

使用 -P 参数时,Docker 会随机映射一个端口到内部容器开放的网络端口,如下开启一个 nginx 服务:

$ docker run -d -P nginx
e93349d539119dc48dc841e117f6388d6afa6a6065b75a5b4aedaf5fb2a051fc
$ 
$ docker ps 
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                   NAMES
e93349d53911        nginx               "nginx -g 'daemon ..."   11 seconds ago      Up 9 seconds        0.0.0.0:32769->80/tcp   zen_kirch

使用 docker ps 看到,本地主机的 32769 端口被映射到了容器的 80 端口,这时我们通过本机浏览器访问 http://localhost:32769 就会出现 nginx 欢迎页面。

2. 指定端口

使用 -p 参数时,可以指定要映射的端口,并且在一个指定的端口上只可以绑定一个容器。支持的格式有:

  • IP:HostPort:ContainerPort
  • IP:ContainerPort
  • HostPort:ContainerPort

下面开启一个 nginx 服务,将本机 8080 端口映射到容器的 80 端口:

$ docker run -d -p 8080:80 nginx
23e725098712d061a1382f33d6fe54da23ae37597a62f8debdd3731b5f9cc4b9
$ 
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                   NAMES
23e725098712        nginx               "nginx -g 'daemon ..."   8 seconds ago       Up 6 seconds        0.0.0.0:8080->80/tcp    frosty_ptolemy

使用 docker ps 看到,本地主机的 8080 端口被映射到了容器的 80 端口,这时我们通过本机浏览器访问 http://localhost:8080 就会出现 nginx 欢迎页面。

3. 查看映射端口

使用 docker port 命令来查看当前映射的端口配置,也可以查看到绑定的地址。命令格式如下:

$ docker port CONTAINER [PRIVATE_PORT[/PROTO]]

容器有自己的内部网络和 IP 地址,可以使用 docker inspect + 容器ID 获取容器的具体信息。

三、容器互联

容器的互联(linking)是一种让多个容器中应用进行快速交互的方式。它会在源和接收容器之间创建连接关系,接收容器可以通过容器名快速访问到源容器,而不是指定具体的 IP 地址。

下面使用 mysql 和 wordpress 镜像来搭建 wordpress 运行环境,演示容器互联的使用。

1. 自定义容器名

连接系统依据容器的名称来执行。虽然创建容器时系统会默认分配一个名字,但建议自己自定义命名。

首先启动一个 mysql 容器,使用 --name 标记自定义容器名为 db:

$ docker run --name db -d -e MYSQL_ROOT_PASSWORD=123456 mysql:latest
35bd73d4d41370bb5218818f58b7f1b89744728c4cb6317d85634abdb47da461
$ 
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
35bd73d4d413        mysql:latest        "docker-entrypoint..."   11 seconds ago      Up 10 seconds       3306/tcp            db

使用 docker ps 可以看到该容器的 NAMES 为 db。

注:-e MYSQL_ROOT_PASSWORD=123456 是为 mysql 服务设置密码,具体可以查看 mysql 镜像的使用。

2. 容器互联

使用 --link 参数可以让容器之间安全地交互。--link 的参数格式为 --link name:alias,其中 name 是要连接的容器名称,alias 是这个连接的别名。

下面启动一个 wordpress 容器,并将它连接到 db 容器:

$ docker run --name wp --link db:mysql -d -p 8080:80 wordpress:latest
d9ee6660b48f80328d14e7a2a57013e72fa8d88de8524d651e003940563e3090
$ docker ps 
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
d9ee6660b48f        wordpress:latest    "docker-entrypoint..."   5 seconds ago       Up 4 seconds        0.0.0.0:8080->80/tcp   wp
35bd73d4d413        mysql:latest        "docker-entrypoint..."   18 minutes ago      Up 18 minutes       3306/tcp               db

此时,wp 容器和 db 容器建立了互联关系。

在浏览器中访问 http://localhost:8080/ 会进入 wordpress 安装程序,安装完成后进入容器 db,你会发现数据表确实被写在该容器中。

注:如提示数据库连接错误,先进入 db 容器新建数据库,如默认名为 wordpress。


本文为博主学习笔记,首发于马燕龙个人博客,欢迎分享,转载请标明出处。
马燕龙个人博客:https://www.mayanlong.com
马燕龙个人微博:http://weibo.com/imayanlong
马燕龙Github主页:https://github.com/yanlongma

Docker 学习笔记 - Docker 数据管理

一、前言

生产环境使用 Docker 的过程中,往往需要对数据进行持久化或者需要在多个容器之间进行数据共享,这必然涉及容器的数据管理操作。

容器中管理数据主要有两种方式:

  1. 数据卷(Data Volumes):容器内数据直接映射到本地主机环境;
  2. 数据卷容器(Data Volumes Containers):使用特定容器维护数据卷;

二、数据卷

数据卷是一个可供容器使用的特殊目录,它将主机操作系统目录直接映射进容器,类似 Linux 的 mount 操作。

数据卷可提供很多有用的特性,如下:

  • 数据卷可以在容器之间共享和重用,容器间传递数据将变得高效方便;
  • 对数据卷内数据的修改会立马生效,无论是容器内操作还是本地操作;
  • 对数据卷的更新不会影响镜像,解耦了应用和数据;
  • 卷会一直存在,直到没有容器使用,可以安全的卸载他。

1. 在容器内创建一个数据卷

使用 docker run 命令时,使用 -v 参数可以在容器内创建一个数据卷。多次使用 -v 标记可以创建多个数据卷。

下面使用 ubuntu 镜像创建一个容器,并创建一个数据卷挂载到容器的 /myvolumes 目录:

$ docker run -it -v /myvolumes ubuntu
root@35ebd0dccc3d:/#
root@35ebd0dccc3d:/# ls 
bin  boot  dev  etc  home  lib  lib64  media  mnt  myvolumes  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

2. 挂载一个主机目录作为数据卷

使用 -v 参数也可以挂载一个本地的已有目录到容器中作为数据卷。这个特性非常适合用于开发,下面演示使用 nginx 镜像创建一个容器运行 nginx 服务并挂载数据卷。

首先通过 nginx 镜像创建一个最基本的服务:

$ docker run --name nginx-server1 -d -p 8081:80 nginx
b3faaf910a6653fc2b2d1c99672a98bdaafd89f07eacf229e355192ee0c1cc16

这时我们通过本机浏览器访问 http://localhost:8081 会出现一个经典的 nginx 欢迎页面,如果想修改页面,只能进入容器修改,显然这并不服务我们的开发习惯。

下面通过 nginx 镜像创建一个服务,并挂载一个本地目录 /html 作为数据卷,html 目录下有一个 index.html 文件,内容为 Hello, Data Volumes !,命令如下:

$ docker run --name nginx-server2 -d -p 8082:80 -v /html:/usr/share/nginx/html nginx
ee9694da5f5364029d60e22f9136991017c76c2f40e7f8742c49173d4cc1905a

这时我们通过本机浏览器访问 http://localhost:8082 就会出现 index.html 页面的内容。修改本机 index.html 中的内容后刷新页面,发现页面的内容也随之改变,显然这更符合开发的需求。

三、数据卷容器

如果用户需要在多个容器之间共享一些持续更新的数据,最简单的方式是使用数据卷容器。数据卷容器也是一个容器,但是它的目的是专门用来提供数据卷供其它容器挂载。

首先创建一个数据卷容器 dbcontainer,并在其中创建一个数据卷挂载到 /dbdata:

$ docker run --name dbcontainer -it -v /dbdata ubuntu
root@af3425b83313:/# 
root@af3425b83313:/# ls 
bin  boot  dbdata  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

然后,其它容器可以使用 --volumes-from 来挂载 dbcontainer 容器中的数据卷,例如创建 web1 和 web2 两个容器,并从 dbcontainer 容器中挂载数据卷:

$ docker run -it --name web1 --volumes-from dbcontainer ubuntu
$ docker run -it --name web2 --volumes-from dbcontainer ubuntu

这时容器 web1 和 web2 都挂载同一个数据卷到相同的 /dbdata 目录。三个容器任何一方在该目录下的写入,其它容器都能看到。


本文为博主学习笔记,首发于马燕龙个人博客,欢迎分享,转载请标明出处。
马燕龙个人博客:https://www.mayanlong.com
马燕龙个人微博:http://weibo.com/imayanlong
马燕龙Github主页:https://github.com/yanlongma

Docker 学习笔记 - Docker 仓库

一、概念

仓库(Repository)是集中存放镜像的地方,分公共仓库和私有仓库。一个容易与之混淆的概念是注册服务器(Registry)。实际上注册服务器是存放仓库的具体服务器,一个注册服务器上可以有多个仓库,而每个仓库下面可以有多个镜像。

docker-repository.jpg

例如对于仓库地址 hub.docker.com/ubuntu,其中 hub.docker.com 是注册服务器地址,ubuntu 是仓库名。

二、仓库

1. Docker Hub 官方仓库

Dcoker Hub 是 Docker 官网维护的一个公共镜像仓库。

2. 国内镜像市场

国内的镜像市场非常多,比较知名的有下面这些:

阿里云:https://dev.aliyun.com/search.html
时速云:https://hub.tenxcloud.com
网易蜂巢:https://c.163.com
DaoCloud:https://www.daocloud.io

不会翻墙的可以优先考虑使用国内镜像。

3. 搭建本地私有仓库

如果有需要可以选择自己搭建本地私有仓库。


本文为博主学习笔记,首发于马燕龙个人博客,欢迎分享,转载请标明出处。
马燕龙个人博客:https://www.mayanlong.com
马燕龙个人微博:http://weibo.com/imayanlong
马燕龙Github主页:https://github.com/yanlongma

Docker 学习笔记 - Docker 容器命令汇总

一、概念

容器是 Docker 的另一个核心概念。简单来说,容器是镜像的一个运行实例。所不同的是,镜像是静态的只读文件,而容器带有运行时需要的可写文件层。

如果认为虚拟机是模拟运行的一整套操作系统(包括内核、应用运行态环境和其他系统环境)和跑在上面的应用,那么 Docker 容器就是独立运行的一个(或一组)应用,以及它们必须的运行环境。

下面总结了常用的容器相关命令。

二、查看容器

查看容器信息相关命令,下面会用到:

docker ps        列出所有启动状态的容器
docker ps -a     列出所有容器
docker ps -qa    列出所有容器 ID

三、创建容器

1. 新建容器

使用 docker create 命令新建一个容器,会产生容器 ID,例如:

$ docker create -it ubuntu:latest
ba8bc0e5995e56a76ae0361687316ce6062247752c6754d2b16bc135e306233f

使用 docker create 命令新建的容器处于停止状态,我们可以使用 docker ps -a 查看:

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS               NAMES
ba8bc0e5995e        ubuntu:latest       "/bin/bash"         About a minute ago   Created                                 brave_engelbart 

2. 启动容器

使用 docker start 命令来启动一个已经创建的容器,例如启动刚创建的 ubuntu 容器(使用上面产生的容器 ID):

$ docker start ba8b
ba8b

再用 docker ps 查看,可以看到该容器处于启动状态:

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
ba8bc0e5995e        ubuntu:latest       "/bin/bash"         18 minutes ago      Up 10 minutes                           brave_engelbart

3. 新建并启动容器

使用 docker run 可以直接新建并启动容器:

$ docker run ubuntu:latest /bin/echo 'Hello World'
Hello World

使用 -t 参数将启动一个 bash 终端,允许用户交互:

$ docker run -it ubuntu:latest /bin/bash
root@976214c9686c:/#

有时需要让 Docker 容器在后台以守护态形式运行,可以通过添加 -d 参数来实现。

四、终止容器

使用 docker stop 命令来终止一个运行中的容器。例如终止上面的 ba8b 容器:

$ docker stop ba8b
ba8b

五、进入容器

使用 docker exec 命令可以进入一个启动状态的容器中,例如下面启动 ba8b 容器并进入:

$ docker start ba8b
ba8b
$ docker exec -it ba8b /bin/bash
root@ba8bc0e5995e:/# 

六、删除容器

使用 docker rm 命令可以删除处于终止或退出状态的容器,该命令格式为:

$ docker rm [OPTIONS] CONTAINER [CONTAINER...]

选项为:

-f, --force     强行终止并删除运行中的容器
-l, --link      删除容器的连接
-v, --volumes   删除容器挂载的数据卷

例如强制删除运行中的 ba8b 容器:

$ docker rm -f ba8b
ba8b

七、导出和导入容器

1. 导出容器

使用 docker export 可以导出容器到文件,不管此时容器处于什么状态。

下面导出一个容器 ID 为 fd15 的容器到文件:

$ docker export -o test1.tar fd15

也可以:

$ docker export fd15 > test2.tar

2. 导入容器

导出的文件又可以使用 docker import 命令导入变成镜像,下面将导出的 test1.tar 文件导入到本地镜像库中:

$ docker import test1.tar  yanlongma/ubuntu:20171030

本文为博主学习笔记,首发于马燕龙个人博客,欢迎分享,转载请标明出处。
马燕龙个人博客:https://www.mayanlong.com
马燕龙个人微博:http://weibo.com/imayanlong
马燕龙Github主页:https://github.com/yanlongma