docker学习笔记1:docke环境的查看
一、环境检查
当登录一个安装了docker的机器后,首先我们要检查下docker环境如何。
1、命令:docker -v 上述命令返回安装的docker的版本信息,返回的信息可能如下:
Docker version 1.9.1, build a34a1d5
说明:执行这个命令不需要docker守护进程已经启动,但其它docker命令基本上都需要docker守护进程已经启动。
2、命令:docker version 上述命令返回安装的docker的版本详细信息,分客户端和服务器。如:
Client:
Version: 1.9.1
API version: 1.21
Go version: go1.4.3
Git commit: a34a1d5
Built: Fri Nov 20 17:56:04 UTC 2015
OS/Arch: linux/amd64
Server:
Version: 1.9.1
API version: 1.21
Go version: go1.4.3
Git commit: a34a1d5
Built: Fri Nov 20 17:56:04 UTC 2015
OS/Arch: linux/amd64
复制代码
说明:执行这个命令时,如果docker守护进程没有启动,则只会返回client的信息。server信息不会显示,会提示无法连接到docker daemon。
3、查看docker守护进程的状态
命令:sudo status docker 如果docker守护进程已经启动,则可能显示的信息如下:
docker start/running, process 1491
否则,可能显示的信息如 docker stop/waiting
4、启动/停止docker守护进程服务
启动: sudo start docker
停止:sudo stop docker
5、查看docker环境的信息
命令:docker info 执行该命令,前提需要docker守护进程已经启动。如果一切正常,会返回如下的信息(这里只提供前面一部分)
Containers: 1
Images: 4
Server Version: 1.9.1
Storage Driver: aufs
Root Dir: /var/lib/docker/aufs
Backing Filesystem: extfs
Dirs: 6
Dirperm1 Supported: false
Execution Driver: native-0.2
Logging Driver: json-file
Kernel Version: 3.13.0-32-generic
Operating System: Ubuntu 14.04.1 LTS
二、查看docker主机上已有的docker镜像
命令:docker p_w_picpaths 执行该命令,会列出主机上已经下载的docker镜像,信息如
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
ubuntu latest ce76de2e871b 7 days ago 188 MB
说明,本地镜像都保存在主机的 /var/lib/docker 目录下。
三、查看dokcer主机上已经创建的容器
命令: docker ps -a -q
说明
-a表示列出所有容器(包括停止运行的容器),否则只会列出运行中的容器。
-q表示只返回容器ID信息,其它容器信息(如状态、对应的镜像等)不显示。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3d72d0283dc8 ubuntu "/bin/bash" 4 days ago Exited(130) 4 days ago stupefied_kare
docker学习笔记2:容器操作
一、列出主机上已经创建的容器 docker ps -a
二、创建交互式容器 docker run -i -t ubuntu /bin/bash
其中-i -t 表示创建一个提供交互式shell的容器。
ubuntu是镜像名,如果本地不存在,回到仓库中下载。
/bin/bash 是指定容器创建后立即执行的命令。
注意:每个容器都有一个唯一的ID,作为容器的标识。每个容器也有个唯一的名称,在用docker run命令创建时可以通过 --name 名称 来指定,如果不指定,系统会自动产生一个名称。
如: docker run --name mycontainer -i -t ubuntu /bin/bash
对于交互式容器,当退出shell后,容器会关闭。 后面可以通过命令重新启动容器。
三、启动/停止容器
如果一个容器已经停止,可以执行如下docker start命令重新启动容器,参数可以是容器的ID 或容器的名称。
docker start 3d72d0283dc8 执行后返回容器的ID
注意,如果指定的容器已经处于启动状态,上述命令只是返回容器ID,不会重新启动容器。
如果要想重启已经启动的容器,可以用 docker restart命令
如果要停止一个运行的容器,可以用 docker stop命令,kill命令也可停止容器,但这命令时强制立即停止容器。
四、附着到交互式容器上
当重新启动容器时,会沿用创建容器(docker run)命令时指定的参数来运行。如果创建容器时,指定了shell。
重启容器时,可以用 docker attach命令附着到容器上,当执行docker attach命令时(可能需要敲下回车键),就回到了容器的bash提示符,
这时就已经相当于在容器内部了的shell操作了。如果操作过程中,退出了shell。容器也会随之停止。
所以这种容器一般是完成特定任务的,不适合运行服务程序。
五、创建守护式容器
这种容器指容器可以长期一直运行,没有交互式会话,非常适合容器中运行后台应用程序和服务(如数据库服务、web服务器等)。
docker run --name mydaemon -d ubuntu /bin/sh -c "while true;do echo hello world;sleep 1;done"
上述语句利用-d标识创建了一个守护式容器,该容器启动了一个shell,循环打印一个信息,保证shell不退出。
可以通过docker logs命令来获取容器的日志 ,还可以通过 docker top 命令来查看容器内当前运行的进程信息。
六、与守护式容器交互
可以通过docker exec命令在容器内部额外启动新进程。
如在主机中,执行语句 docker exec -t -i mydaemon /bin/bash
则会出现一个shell会话(容器内的,不是主机的),这样就可以和容器进行交互了,可以完成自己想要的操作。
七、查看容器详细信息
利用docker logs 命令可以获取容器的日志信息。
利用docker inspect 命令可以查看容器更多的信息。 如ip地址等,这对守护容器还是很有意义的。
八、执行容器内命令
可以在docker主机上,执行 docker exec命令, 在容器内部启动新的进程。
docker exec -i -t 容器ID/NAME /bin/bash
上面命令表示在容器内打开一个shell交互式会话,参数 -i -t 是让这个shell能被主机捕捉到,可以在主机上操作该shell。通过这个命令,就可以对容器进行相关的操作了,如进行容器的配置、应用程序的配置等。
注意:这个方式和attach不同。attach绑定的shell退出后容器会退出。这种方式不会。
九、删除容器 命令:docker rm ID/NAME 注意,运行中的容器是无法被删除的。
注意:在利用docker run创建容器时,可以加上标识 --rm,会在容器运行完毕后,自动删除容器,相当于创建的是一个一次性容器。如:
docker run --rm ....... 这个尤其在练习容器的操作使用时非常使用,省去了留下一堆垃圾容器需要人工清理的工作。
十、查看容器的内容改变信息
创建一个容器,会在容器的对应的镜像上增加一个可写层,镜像部分是只读的。通过 diff命令可以看出改变的信息。如:
xxx@ubuntu:~$ docker diff mysqldb
A /hello
C /root
A /root/.bash_history
A /root/.mysql_history
C /run
C /run/mysqld
A /run/mysqld/mysqld.pid
A /run/mysqld/mysqld.sock
A /run/mysqld/mysqld.sock.lock
C /tmp
说明:每行代表一个变动的文件或目录。其中 A 表示新增、C表示被修改、D表示被删除(这个例子没有体现)。
十一、主机和容器之间的文件拷贝
很多场景下,我们需要从主机将文件拷贝到容器中,或从容器拷贝文件都主机。利用 cp命令即可,语法格式如下:
docker cp 主机路径 ID/NAME:容器路径 //这是从主机拷贝文件到容器
docker cp ID/NAME:容器路径 主机路径 //这是从容器拷贝文件到主机
十二、创建容器
我们上面的介绍都是用 docker run 创建容器,并在创建成功后立即启动该容器。
还有另外一个docker create命令,该命令使用格式同run命令,但它只创建容器,不会立即启动。要想运行容器,需要单独再执行启动命令。
需要注意的是,使用docker create创建守护容器时,不能带-d标识符。
实际上无论是 run ,还是create命令,都有大量可选的参数,我们这里只是介绍最基本的使用方式(也就是说使用尽量少的参数)。在实际生产环境中,往往会更加复杂。
十三、重命名容器
每个一个容器除了ID外,都有一个name(可以在创建时指定,也可以不指定,由系统自动分配)。
当容器创建后,也可以通过rename命令给容器重命名。重命名时,容器处于运行或停止状态都允许修改。
语法格式: docker rename oldname newname
这个命令还是挺有用的,当一个容器的name不适合时,就需要重新创建,只需修改名称即可。
docker学习笔记3:镜像操作(查找和下载)
一、查看本地镜像
只有下载后,镜像才会保存在本地(docker环境所在的主机),通过如下命令可以查看本地已经存在的镜像。
命令:dokcer p_w_picpaths 该命令列出本地所有已经存在的镜像,显示的信息如:
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
ubuntu latest ce76de2e871b 8 days ago 188 MB
说明:docker p_w_picpaths 命令可带参数,是个字符串,可以带通配,只显示过滤的镜像。
二、镜像中心
本地的镜像是从远程镜像中心(Registry)下载到本地的,默认的镜像中心是docker公司负责运营的docker hub中心。
在远程镜像中心,镜像是保存在仓库(Repository)中,仓库存在镜像中心(Registry)中。
每个镜像都有一个唯一的ID号。 一个仓库(如上面的ubuntu)中有多个镜像,通过tag标识来区分不同镜像,一个仓库中的镜像通常是同一种类型的镜像,只是不同版本的区别。换句话说,镜像时由仓库名和tag标识来共同决定的。
docker hub中有两种类型的镜像:用户仓库(user repository)和顶层仓库(top-level repository)。
用户仓库的镜像是有docker用户创建的。顶层仓库是有docker公司内部管理的。
用户仓库的命名由用户名和仓库名两部分组成(中间用/分隔);而顶层仓库只有仓库名,如ubuntu仓库。
总结一下,镜像名称的标准格式是: 用户名/仓库名:Tag名,对于顶层的则没有用户名,如果省略tag名,默认为latest.
说明:也可以搭建私服的镜像中心,供企业内部使用。
三、在docker hub中心查找仓库
通过docker search命令可以查找docker hub上所有公共的可用仓库。
可以带一个字符串参数(支持通配),用于查找满足命名的仓库。
举例:docker search mysql
显示的内容如:
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relati... 1872 [OK]
mysql/mysql-server Optimized MySQL Server Docker p_w_picpaths. Crea... 110 [OK]
centurylink/mysql Image containing mysql. Optimized to be li... 38 [OK]
sameersbn/mysql 31 [OK]
google/mysql MySQL server for Google Compute Engine 14 [OK]
appcontainers/mysql Centos/Debian/Ubuntu Based Customizable My... 7 [OK]
...................
返回的每条记录代表一个镜像。包含5个字段信息:
1)Name:镜像的仓库名。可以看出顶层仓库只有第一个镜像是。其它的都是用户仓库。
2)Description:仓库的描述信息
3)Stars:用户评价,反映一个仓库受欢迎的程度
4)Offical:是否官方,即是否是顶层仓库。可以看出,只有第一个镜像是顶层仓库。
5)Automated:表示这个镜像是由docker hub自动构建的。
四、下载镜像
通过docker run方法是创建容器,如果指定的镜像在本机不存在,则会先去下载镜像。
可以通过docker pull命令只下载镜像,不创建容器。
命令: docker pull [用户名/]仓库名[:TAG]
含义: 如果只指定仓库名,会下载该仓库下的所有镜像。如果还指定了TAG值,则会下载指定的镜像。
对于dokcer run命令,只指定仓库名,不指定tag时,默认下载的是 latest标识的镜像。
xxx@ubuntu:~$ docker p_w_picpaths
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
ubuntu latest ce76de2e871b 8 days ago 188 MB
xxx@ubuntu:~$ docker pull mysql
Using default tag: latest
latest: Pulling from library/mysql
73e8d4f6bf84: Pull complete
040bf8e08425: Pull complete
86e6c3163927: Pull complete
68f4b3625ea4: Pull complete
04f7e78a2c8a: Pull complete
1bade56c3b6b: Pull complete
dd6387e14c18: Pull complete
ca30c0626c9b: Pull complete
0dc5e226a795: Pull complete
6c164b0f04cb: Pull complete
5c74d058f7b5: Pull complete
0fd3b6e12567: Pull complete
e8126a9d061e: Pull complete
d17cffff8039: Pull complete
1924f4186d05: Pull complete
14961e5db73a: Pull complete
Digest: sha256:16de02081c408c41361126aaa718f91693688d39a216a74ac8dab841db050228
Status: Downloaded newer p_w_picpath for mysql:latest
xxx@ubuntu:~$ docker p_w_picpaths
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
mysql latest 14961e5db73a 4 days ago 361.3 MB
ubuntu latest ce76de2e871b 8 days ago 188 MB
镜像下载后,就可以通过docker run命令创建相应的容器了。
五、镜像的复制
一个镜像是属于一个仓库,一个仓库中有多个镜像,大家靠tag来区分。
在某些场景下,可能需要把一个已有的镜像 加入(也就是复制)到别的仓库中。这时可以用tag命令。具体的语法格式是:
docker tag [OPTIONS] orignIMAGE[:TAG] [REGISTRYHOST/][USERNAME/]newNAME[:TAG]
这个还是挺有用的,比如当创建一个镜像,命名不适合(仓库名和TAg标识),这样相当于改个名,但实际是拷贝一份。
docker学习笔记4:利用docker hub上的mysql镜像创建mysql容器
docker hub上有官方的mysql镜像,我们可以利用它来创建mysql容器,作为一个服务容器使用。
1、下载mysql镜像
docker pull mysql
2、创建镜像
docker run --name mysqldb -e MYSQL_ROOT_PASSWORD=root -d mysql
3、获取被创建容器的ip
docker inspect mysqldb
4、从主机上利用mysql客户端测试能否连接到容器中的mysql服务
mysql -h 172.17.0.2 -u root -p
上面的ip地址是mysqldb容器的ip地址,通过docker inspect mysqldb获取到的
docker学习笔记5:利用commit命令创建镜像 和 删除本地镜像
一、概述
创建镜像有两种方法,一是用commit命令,二是用dockerfile方法(这个更常用,在下面文章介绍)。本章介绍commit方法。
在介绍commit命令前,我们先回顾下对代码的版本控制,当修改代码后,我们会commit变更到版本服务器上。
对于容器类似的概念,当创建容器后,如果后面对容器做了修改,就可以利用commit命令将修改提交为一个新的镜像。
二、例子说明
下面我们通过具体的例子来说明:
1、创建新容器
docker run --name newcontent -i -t ubuntu /bin/bash
2、进行操作,修改容器内容
echo hello world >>test.txt //通过重定向功能创建一个文件
3、退出shell,容器关闭
4、用diff命令查看容器的变化信息
xxx@ubuntu:~$ docker diff newcontent
C /root
A /root/.bash_history
A /test.txt
5、创建新镜像
docker commit newcontent newnewcontent2
这时就在本地创建了一个仓库名为newnewcontent2,tag值为默认为latest的镜像。
规范的镜像名应该为:[username/]repositoryName[:tagName]
如:docker commit newcontent jeme/myubuntu:1.0 如果没有tagName,则默认为latest。
注意:如果需要把该镜像提交到dokcer hub中心,则必须规范命名(必须是 用户名/仓库名,tag可以缺省),前面的用户名是在dokcer hub上注册的用户名。
三、删除本地镜像 docker rmi 镜像名/ID
docker学习笔记6:利用dockerfile创建镜像介绍(生成简单web服务器镜像)
本文介绍如何利用dockerfile来创建镜像。下面介绍具体的操作过程:
一、创建构建环境
操作示例如下:
xxx@ubuntu:~$ pwd
/home/xxx
xxx@ubuntu:~$ mkdir myweb
xxx@ubuntu:~$ cd myweb
xxx@ubuntu:~/myweb$ touch Dockerfile
上面命令在当前用户(xxx)的主目录下创建了一个myweb目录,并在该目录下建立了一个空的文件名为Dockerfile文件。
这个目录就是我们的构建环境(或上下文)。
二、编写Dockerfile文件内容
Dockerfile文件中,是一系列的指令组成。每条指令,包括指令名(必须大写)和指令所需的参数。看一个例子:
# version:0.0.1
FROM ubuntu
MAINTAINER XXX "[email protected]"
RUN apt-get update
RUN apt-get install -y nginx
RUN echo 'hello, i am a web p_w_picpath' > /usr/share/nginx/html/index.html
EXPOSE 80
文件的第一行是一条注释,在dockfile文件中,以#开头的表示注释。
当执行dockerfile文件时(如何执行,后面会介绍),其流程如下:
1、从基础镜像运行一个容器(第一条FROM指令的参数用于指定一个已经存在的基础镜像,每个dockerfile文件的第一条指令都是FROM)
2、在上面创建的容器中,执行一条指令,对容器做出修改(一般指令总会对容器进行一些改变,否则该指令就不需要了)
3、执行类似docker commit命令,提交一个新的镜像层(该层的内容就是上面指令造成的变化内容)
4、基于刚提交的镜像运行一个新的容器。
5、重复2~4步骤,逐个执行dockerfile中的所有指令。
看到这里大家可以有个疑问,为何每条指令都要创建镜像和容器呢,而不是只在开始创建一次容器,然后基于该容器执行所有指令,完成所有修改后,再提交生成一个镜像呢?
这正是docker镜像分层特点的优势。可以想象一下,采用这种放的好处是,即使因为某种原因导致某条指令失败,但我们还是可以得到一个可用的镜像,然后我们就可以通过该镜像运行一个容器,在该容器中执行失败的指令,从而方便的进行调试,找到失败原因。
下面我们来介绍上面dokcerfile文件中每一行的意义:
1、第一行上面已经介绍,以#开头,是注释。
2、第二行FROM指令,用于指定基础镜像。是所有dockerfile的第一条命令。因为所有新的镜像都会基于该基础镜像基础上变化来的。
3、第三行 MAINTAINER指令,是标识镜像的作者和联系方式(这里是电子邮件),以方便镜像使用者和作者联系。
4、第四~六行RUN指令,用于在容器中执行参数指定的命令。上面的例子第4行是更新已经安装的APT仓库,第5行是下载安装nginx包,第6行是生成一个html文件,文件中只包含简单的一句话。
5、最后一行EXPOSE指令,告诉docker守护进程,容器的应用将使用指定的端口号(EXPOSE指令的参数,这个例子是80)。
三、构建镜像
通过docker build命令运行dockerfile文件,最后生成需要的镜像。命令如:docker build -t="jene/myweb" .
参数-t指定生成镜像的所属用户名和仓库名,也可以有tag标识(这个例子没写,默认为latest)。
 123
 123
 123 123 123
 123
 123
 123 123
""
""
 123
 123
 123 123 123
 123
 123 123
 123
 123
 123
""
""
 123
 123""
""
 123
>
 123
 123
 123
 123 123
 123
 123 123
 123
 123 123
 123 123 123
 123 123 123
 123 123
 123 123 123
 123 123 123
 123 123
 123 123 123
 123 123 123 123
 123 123
 123 123 123
 123 123 123 123
 123 123
 123 123 123 123 123 123 123 123' 123 123 123 123 123 123 123 123 123 123
 123 123 123
 123 123
 123 123 123 123 123 123 123 123 123 123 123 123
 123 123 123 123
 123 123
 123 123 123' 123 123 123 123 123 123 123 123 123 123
 123 123 123 123
 123
 123 123
 123""" 123" 123 123
 123 123 123 123" 123" 123 123
 123 123
 123 123 123
 123 123 123 123 123 123 123
 123 123
 123 123
 123 123 123
 123 123 123 123 123 123 123 123
 123
 123 123
 123 123 123
 123 123 123
 123 123 123
 123 123 123 123
 123 123 123
 123 123 123 123
 123 123
 123 123 123"" 123 123 123"" 123 123 123 123
 123 123 123 123 123
 123 123
 123 123
 123 123 123
 123 123 123 123 123 123 123
 123 123
 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123
 123 123 123 123
 123 123
 123 123 123
 123 123 123 123
 123 123 123 123
 123 123 123 123
 123 123
 123 123 123 123 123 123 123 123 123 123 123 123
 123 123 123 123
 123 123
 123 123 123 123 123 123
 123 123 123 123
 123 123
 123 123 123
 123 123 123 123
 123 123
 123 123 123
 123 123 123 123 123
 123 123 123 123 123
 123 123
 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123
 123 123 123 123
 123 123
 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123
 123 123 123 123
 123
 123 123
 123 123 123"" 123 123 123 123 123 123
 123 123 123 123 123 123
 123 123 123"" 123 123 123 123 123 123 123 123
 123 123 123 123 123
 123 123
 123 123 123
 123 123 123> 123 123 123
 123 123 123
 123 123< 123 123 123
 123 123
 123 123 123 123"" 123 123 123"" 123 123 123"" 123 123 123
 123 123 123
 123 123
 123 123 123
 123 123 123 123
 123 123
 123 123
 123 123
 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123
 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123
 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123
 123 123 123 123 123 123 123"" 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123
 123 123 123 123 123 123
 123 123
 123 123 123 123
 123 123 123 123
 123 123 123 123 123 123
 123 123
 123 123 123
 123 123 123
 123 123
 123 123 123
 123 123 123 123
 123 123 123 123 123 123
 123 123
 123 123 123
 123 123 123 123 123 123 123 123
 123 123
 123 123 123
 123 123 123" 123 123 123 123 123 123
> 123" 123 123
 123 123 123 123
 123 123 123 123 123
 123 123
 123 123 123 123
 123 123
 123 123 123
 123 123 123 123 123 123
 123 123 123
 123 123 123 123 123
 123 123 123
 123 123 123
 123 123
 123<> 123 123
 123 123
 123<><> 123 123
 123 123
 123<> 123 123
 123 123
 123<> 123 123 123 123 123 123 123 123 123 123 123 123
 123"" 123"" 123"" 123 123 123 123 123 123 123
 123 123
 123"""""" 123 123 123 123 123 123 123 123 123 123
 123 123 123 123 123 123 123 123
 123 123
 123"""" 123 123 123 123 123 123 123
 123 123
 123"" 123"" 123"" 123 123 123 123 123 123 123 123
 123 123 123 123 123 123 123 123
 123 123
 123 123 123
 123 123 123 123 123
 123 123 123 123
 123 123
 123 123 123
 123"" 123 123
 123"" 123 123
 123 123
 123 123 123
 123"" 123 123
 123 123 123
 123 123
 123"" 123"" 123"" 123 123
 123 123
 123<> 123<> 123 123
 123 123
 123 123 123
 123 123 123
 123 123 123
 123 123 123 123 123 123
 123 123
 123 123 123
 123 123 123 123 123
 123 123 123
 123 123 123 123 123 123 123 123 123 123
 123 123 123
 123 123 123 123 123 123 123 123 123 123
 123 123
 123<> 123<> 123 123
<><><><><><><><><>
 123 123
 123<> 123<> 123 123
<>
<>
 123 123
 123"<>" 123 123
 123 123
 123 123 123
 123"" 123 123
 123 123
 123 123 123 123 123 123 123 123 123 123
 123 123
 123 123 123
 123 123
 123 123 123 123 123 123 123
 123 123 123 123 123 123 123 123
 123 123
 123<> 123 123
 123 123
 123 123 123 123 123
 123 123 123
 123 123
 123 123 123"" 123 123
 123 123
 123 123 123 123
 123 123" 123 123 123 123"> 123 123 123
 123 123 123 123
 123 123
 123 123 123 123
 123 123 123 123 123 123
 123 123
 123 123 123 123 123
 123 123 123&& 123 123 123 123'' 123 123' 123 123' 123 123 123 123 123
 123 123 123 123 123
 123 123 123 123 123
 123 123
 123 123 123 123 123 123 123 123 123
 123 123 123 123 123 123 123 123 123 123 123
 123 123 123 123 123 123 123 123 123 123 123
 123 123
 123 123 123 123
 123 123
 123 123 123 123
 123 123 123&& 123 123 123'' 123 123 123 123 123
 123 123 123 123 123
 123 123
 123 123 123 123
 123 123 123 123
 123 123
 123 123 123 123
 123 123 123 123 123
 123 123
 123 123 123 123
 123 123 123
 123 123
 123 123 123 123 123
 123 123 123 123&& 123 123 123 123 123
 123 123
 123 123 123
 123 123 123
 123 123
 123 123 123 123
 123 123
 123 123 123 123 123
 123 123
 123 123
 123 123 123 123 123
 123 123
 123 123
 123 123 123 123 123
 123 123 123 123 123
 123 123
 123 123
 123 123 123
 123
 123 123
 123 123 123 123 123 123
 123 123 123 123 123 123 123
<> 123