一. Docker概述与安装

开发一个新项目后,会涉及到环境部署的问题(如MySQL、Redis等),会耗费比较多时间,因此急需一种可以快速打包部署项目并上线的方法。

Docker(一种容器化技术)因此而生。它的思想是隔离,将项目与环境进行打包、装箱,将服务器性能利用到极致。它是一个快速交付、运行应用的技术。

Docker运行到不同操作系统时,打包时会将系统库函数一同打包,最后借助Linux内核运行,实现Linux内核系统的跨平台。

官方文档:https://docs.docker.com/

Docker 和 虚拟机技术有何不同?

  • 传统虚拟机是虚拟出一套硬件,运行一个完整的操作系统,并在操作系统上安装应用

  • Docker容器内应用直接运行在宿主机内核(共享内核),容器相互隔离互不影响

    Docker 虚拟机
    操作系统 与宿主机共享OS 宿主机OS上运行虚拟机OS
    存储大小 镜像小,便于存储和传输 镜像庞大(vmdk vdi等)
    运行性能 几乎无额外性能损失 操作系统额外的CPU、内存消耗
    移植性 轻便、灵活、适用于Linux 笨重,与虚拟化技术耦合度高
    硬件亲和性 面向软件开发者 面向硬件运维者

Docker架构

镜像(image):类似一个模板,可以通过模板来创建容器服务。通过一个镜像可以创建多个容器。它是一种轻量级、可执行的独立软件包,包含运行软件所需的运行时、库、环境变量和配置环境等。

容器(container):独立运行一个或一组应用,可以理解为一个简易的linux系统

仓库(repository):存放镜像的位置

Docker安装

环境查看

1
2
3
4
5
6
# 系统内核
[root@iZ2ze7qxbl1r54zhx9fbs3Z ~]# uname -r
3.10.0-1127.10.1.el7.x86_64

# 系统版本
[root@iZ2ze7qxbl1r54zhx9fbs3Z /]# cat /etc/os-release

安装帮助文档:https://docs.docker.com/engine/install/

按照文档安装完成后

1
2
3
4
5
6
7
8
9
10
11
# 启动Docker
systemctl start docker

# 查看版本
docker version

# 运行hello-world
docker run hello-world

# 查看镜像
docker images

配置阿里云镜像加速服务(控制台->产品与服务->弹性计算->容器镜像服务->镜像加速器)

1
2
3
4
5
6
7
8
9
10
11
sudo mkdir -p /etc/docker

sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://7nonk1j6.mirror.aliyuncs.com"]
}
EOF

sudo systemctl daemon-reload

sudo systemctl restart docker

二. Docker常用命令

帮助命令

1
2
3
4
docker version     # 查看docker版本信息
docker info # 显示docker的信息,包括镜像、容器数量
docker help # 帮助
docker 命令 --help # 记不住命令用法不要紧,用这条命令查看用法

官方文档:https://docs.docker.com/engine/reference/run/

镜像命令

docker images:查看本地主机上的镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@iZ2ze7qxbl1r54zhx9fbs3Z ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest bf756fb1ae65 7 months ago 13.3kB

# 说明
REPOSITORY 镜像的仓库源
TAG 镜像标签
IMAGE ID 镜像ID
CREATED 镜像创建时间
SIZE 镜像大小

# 常用可选项
-a , --all # 列出所有镜像
-q , --quiet # 只显示镜像ID

docker search:搜索镜像

1
2
3
4
[root@iZ2ze7qxbl1r54zhx9fbs3Z ~]# docker search mysql

# 常用可选项,使用filter限制搜索条件(例如下方搜索3000赞以上的镜像)
[root@iZ2ze7qxbl1r54zhx9fbs3Z ~]# docker search mysql --filter=STARS=3000

docker pull:下载镜像

1
2
# 如果不写tag默认latest
docker pull 镜像名[:tag] # 例如 docker pull mysql:5.7

docker rmi:删除镜像

1
2
docker rmi -f 镜像ID或镜像名
docker rmi -f $(docker images -aq) # 删除全部镜像

docker save / docker load:保存或加载镜像

1
2
docker save -o redis.tar redis:latest
docker load -i redis.tar

容器命令

首先,下载一个centos镜像进行测试

1
docker pull centos

新建容器并启动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
docker run [参数] image

# 常用参数
--name # 容器名
--detach # 后台方式运行 -d
-it # 使用交互方式运行
-p # 指定容器端口
# -p ip:主机端口:容器端口
# -p 主机端口:容器端口
# -p 容器端口
-P # 随机指定端口(大写)
--ip # 指定容器运行的ip,要注意user specified IP address is supported on user defined networks only
-net # 运行在指定的网络的名称

# 启动并进入容器
[root@iZ2ze7qxbl1r54zhx9fbs3Z ~]# docker run -it centos /bin/bash

# 退出容器
[root@274f17eaf88a /]# exit

# 查看正在运行容器
[root@iZ2ze7qxbl1r54zhx9fbs3Z ~]# docker ps
-a # 列出历史+现在正在运行的容器
-n=? # 显示最近个数
-q # 只显示容器ID

查看所有容器

1
2
docker container ls -a # 列出所有容器
docker system df -v # 占用空间情况

退出容器

1
2
exit  # 容器停止并退出
Ctrl+P+Q # 容器不停止并退出

删除容器

1
2
docker rm 容器ID	# 删除容器
docker rm -f $(docker ps -aq) # 删除所有容器

启动与停止容器

1
2
3
4
5
6
docker start 容器ID    # 启动
docker restart 容器ID # 重启容器
docker stop 容器ID # 停止容器
docker kill 容器ID # 强制停止
docker pause 容器ID # 暂停容器(将进程挂到内存)
docker unpause 容器ID # 恢复暂停的容器

其他命令

后台启动容器

1
2
[root@iZ2ze7qxbl1r54zhx9fbs3Z ~]# docker run -d centos
# 注意:使用后台运行,需要有一个前台进程,否则会自动停止

日志查看

1
2
3
# docker logs -tf --tail 条数 容器ID
# -t为显示时间戳, -f为跟踪日志输出
[root@iZ2ze7qxbl1r54zhx9fbs3Z ~]# docker logs -tf --tail 10 f6baeea082b1

查看容器中进程信息

1
2
# docker top 容器ID
[root@iZ2ze7qxbl1r54zhx9fbs3Z ~]# docker top f6baeea082b1

查看镜像数据源

1
2
# docker inspect 容器ID
[root@iZ2ze7qxbl1r54zhx9fbs3Z ~]# docker inspect f6baeea082b1

进入当前正在运行容器

1
2
3
4
# docker exec -it 容器ID /bin/bash
# docker attach 容器ID
[root@iZ2ze7qxbl1r54zhx9fbs3Z ~]# docker exec -it f6baeea082b1 /bin/bash
[root@iZ2ze7qxbl1r54zhx9fbs3Z ~]# docker attach f6baeea082b1

从容器内拷贝文件到主机

1
docker cp 容器ID:文件路径 主机路径

容器内安装 sudo

1
2
apt-get update
apt-get -y install sudo

查看网络信息

1
docker network inspect bridge

创建网络

1
docker network create -d bridge --subnet 172.20.0.0/24 network_name

三. 安装练习

仓库推荐:DockerHub

可视化面板推荐:portainer

安装Nginx

1
2
3
4
5
6
7
8
9
# 1.搜索并拉取镜像
docker search nginx
docker pull nginx

# 2.新建容器并启动 -d为后台运行,名字为nginx01,本机端口3344,容器端口80
docker run -d --name nginx01 -p 3344:80 nginx

# 3.访问测试
curl localhost:3344

安装Tomcat

1
2
3
4
5
6
7
8
# 直接安装
docker run -it --rm tomcat:9.0 # 测试,用完即删

# 下载再启动
docker pull tomcat

# 启动
docker run -d --name tomcat01 -p 3345:80 tomcat

安装ES+head插件+Kibana

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 启动
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.8.1

# 注意:安装完后会发现内存占用很大,服务器十分卡顿
docker stats # 查看服务器资源状态

# 启动时限制内存在64MB-512MB -e ES_JAVA_OPTS="-Xms64m -Xmx512m"
docker run -d --name elasticsearch02 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.8.1

# 拉取并安装head监控管理插件
docker pull mobz/elasticsearch-head:5
docker run -d -p 9100:9100 docker.io/mobz/elasticsearch-head:5

# 安装kibana
docker run --name kibana -e ELASTICSEARCH_URL=http://39.97.107.13:9200 -p 5601:5601 -d kibana:7.8.1

补充:在使用宝塔 Docker 部署 ES 时,要注意填写的内存大小,资源不足会导致容器停止运行。对于2G内存服务器来说,建议填写400MB限制,同时对镜像提供运行环境参数:discovery.type=single-nodeES_JAVA_OPTS=-Xms64m -Xmx160m

安装portainer

在网上发现一个不错的Docker可视化工具

1
2
3
docker volume create portainer_data

docker run -d -p 9000:9000 --name portainer --restart always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce

四. 镜像原理与数据卷

镜像加载

联合文件系统(UnionFS)

是一种分层、轻量级且高性能的文件系统,支持对文件系统的修改作为一次提交来以层层叠加。它是Docker镜像的基础。

Docker镜像加载原理

Docker镜像实际上由一层层文件系统组成,这种层级文件系统就是 UnionFS。

总的来说,镜像是将应用程序的及其需要的系统函数库、环境、配置和依赖打包而成。

Q:为什么CentOS镜像那么小?

A:精简后的OS,rootfs(root file system)可以非常小,只需包含基本命令、工具和程序库。对于不同Linux发行版,bootfs(boot file system)基本一致,只是rootfs有差别。

特点

Docker镜像都是只读,当容器启动时一个新的 可写层 会被加载到镜像顶部。

这一层也被称为 容器层,容器以下的都是 镜像层

镜像结构:入口(Entryppoint)、层(Layer)、基础镜像(BaseImage)

镜像提交

1
docker commit -m="描述信息" -a="作者名" 容器id 目标镜像名:[TAG]

容器数据卷管理

将Docker容器内产生的数据同步到本地,相当于挂载到宿主机上。这样一来,就算将容器不小心删除了,我们的数据还是能得到保存。(容器与数据分离,解耦合,方便操作容器内数据,保证数据安全)

需要注意的是,-v是将本地目录挂载到容器内,如果本地目录为空,在容器中查看对应的目录也会为空。

方法一:目录或文件直接挂载

1
2
3
4
5
6
7
docker run -it -v 主机目录:容器内目录 -p

# 查看挂载情况 "Mounts"属性
docker inspect 容器ID

# MySQL数据挂载测试,注意-e配置参数,参考dockerhub
docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw=123456 --name mysql01 mysql:5.7

方法二:数据卷挂载

1
2
3
4
5
6
# 创建数据卷
docker volume create html
# 挂载,如果没创建数据卷Docker会自动创建
docker run --name mn -v html:/usr/share/nginx/html -p 80:80 -d nginx
# 或者通过 --volumes-from 实现两个容器的数据卷同步
docker run -it --name docker-2 --volumes-from docker-1 92f4cfd1ccbe

方法三:启动容器后追加挂载

第一步:使用docker ps查看正在运行的容器id(2831a679ab1b)

第二步:找到配置文件/var/lib/docker/containers/<容器ID>/config.v2.json,注意macOS上的Docker需要用特殊方法找到配置文件。

第三步:修改配置文件,这里暂时还没试过,TODO。

匿名挂载与具名挂载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 匿名挂载,只写容器内路径
docker run -d -P --name nginx01 -v /etc/nginx nginx
# 查看卷情况
[root@iZ2ze7qxbl1r54zhx9fbs3Z /]# docker volume ls
DRIVER VOLUME NAME
local 5c0348ebc465674851391d48a81cecdd91a9f4c52ec09209a49e68ab4ce33f22

# 具名挂载 卷名:容器内路径
docker run -d -P --name nginx01 -v nginx_juan:/etc/nginx nginx

# 可以通过 ro rw 改变容器读写权限
ro readonly 只读
rw readwrite 可读写
# 例如
docker run -d -P --name nginx01 -v nginx_juan:/etc/nginx:ro nginx

DockerFile简介

它是一个构建docker镜像的文件,是命令参数脚本。

步骤:

  1. 编写一个 dockerfile 文件
  2. docker build 构建一个新镜像
  3. docker run 运行镜像
  4. docker push 发布镜像(dockerhub、阿里云镜像仓库等)

举例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 创建dockerfile
FROM centos
VOLUME ["volume01","volume02"] # 挂载目录,启动后会在根目录创建
CMD echo "---end---"
CMD /bin/bash

# 测试新建容器 -f dockerfile文件名 -t 镜像名:版本号
[root@iZ2ze7qxbl1r54zhx9fbs3Z ceshi]# docker build -f /home/ceshi/dockerfile1 -t banana_centos:1.0 .
Sending build context to Docker daemon 3.072kB
Step 1/4 : FROM centos
---> 831691599b88
Step 2/4 : VOLUME ["volume01","volume02"]
---> Running in 8ca74a22f596
Removing intermediate container 8ca74a22f596
---> 665e599d4961
Step 3/4 : CMD echo "---end---"
---> Running in 5a0de7cd643b
Removing intermediate container 5a0de7cd643b
---> 23d0d3685d01
Step 4/4 : CMD /bin/bash
---> Running in 84671b255a0b
Removing intermediate container 84671b255a0b
---> 92f4cfd1ccbe
Successfully built 92f4cfd1ccbe
Successfully tagged banana_centos:1.0

构建过程

基础知识:

  1. 每个关键字指令必须是大写字母
  2. 从上到下按顺序执行
  3. 注释符号是 #
  4. 每个指令都会创建一个新的镜像层

DockerFile指令与编写

1
2
3
4
5
6
7
8
9
10
11
12
FROM          # 从基础镜像开始构建
MAINTAINER # 维护者信息,姓名+邮箱
RUN # 运行的命令
ADD # 添加文件 如tomcat
WORKDIR # 设置镜像工作目录
VOLUME # 挂载的目录
EXPOSE # 指定对外端口
CMD # 容器运行时要运行的命令,只有最后一个生效
ENTRYPOINT # 容器运行时要运行的命令,可以追加命令
ONBUILD # 构建一个被继承DockerFile时会被触发
COPY # 将文件拷贝到镜像中
ENV # 设置环境变量

创建一个自己的CentOS镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 1.编写dockerfile文件
FROM centos
MAINTAINER banana<798998087@qq.com>

ENV MYPATH /usr/local # 设置工作目录
WORKDIR $MYPATH

RUN yum -y install vim
RUN yum -y install net-tools

EXPOSE 80

CMD echo $MYPATH
CMD echo "---end---"
CMD /bin/bash

# 2.通过文件构建镜像
docker build -f dockerfile文件名 -t 镜像名:版本号 .

创建一个Tomcat镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 1.准备好tomcat与jdk安装包
[root@iZ2ze7qxbl1r54zhx9fbs3Z tomcat]# ls
apache-tomcat-8.5.50.tar.gz jdk-8u241-linux-x64.tar.gz

# 2.编写文件Dockerfile(这是官方命名,用这个名字后构建镜像无需-f指定)
FROM centos
MAINTAINER banana<798998087@qq.com>

COPY readme.txt /usr/local/readme.txt

ADD jdk-8u241-linux-x64.tar.gz /usr/local
ADD apache-tomcat-8.5.50.tar.gz /usr/local

RUN yum -y install vim

ENV MYPATH /usr/local
WORKDIR $MYPATH

ENV JAVA_HOME /usr/local/jdk1.8
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.50
ENV CATALINA_BASH /usr/local/apache-tomcat-8.5.50
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin

EXPOSE 8080

CMD /usr/local/apache-tomcat-8.5.50/bin/startup.sh

# 3.构建镜像,点代表当前所在目录
docker build -t mytomcat .

# 4.创建容器,启动(同时将目录挂载出来方便部署)
docker run -d -p 9090:8080 --name bananaTomcat -v /home/ceshi/tomcat/test:/usr/local/apache-tomcat-8.5.50/webapps/test -v /home/ceshi/tomcat/logs:/usr/local/apache-tomcat-8.5.50/logs mytomcat

创建一个Java项目镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 1.指定镜像基础
FROM ubuntu:16.04

# 2.配置环境变量,JDK的安装目录
ENV JAVA_DIR=/usr/local

# 3.拷贝JDK和Java项目将
COPY ./jdk8.tar.gz $JAVA_DIR/

# 4.安装JDK
RUN cd $JAVA_DIR/ \
&& tar -xf ./jdk8.tar.gz \
&& mv ./jdk1.8.0_144 ./java8

# 5.配置环境变量
ENV JAVA_HOME=$JAVA_DIR/java8
ENV PATH=$PATH:$JAVA_HOME/bin

# 6.放入项目
COPY ./docker-demo.jar /tmp/app.jar

# 7.暴露端口
EXPOSE 8080

# 8.入口
ENTRYPOINT java -jar /tmp/app.jar

实际上,1-5步骤基本不会变,所以可以先打包成一个镜像,然后再根据这个镜像去构建,后期调整会方便很多。在DockerHub上已经有人做了这些事,并上传了这样的镜像(例如 java:8-alpine)。

发布镜像

DockerHub

https://hub.docker.com/ 注册账号后

服务器上提交镜像

1
2
3
4
5
6
7
8
9
10
11
# 登录
docker login -u 账号

# 推送镜像前要记得修改tag
docker tag 镜像ID 账号ID/镜像名:版本号

# 推送(例子)
docker push tj20185584/tomcat:1.0

# 查看仓库
https://hub.docker.com/r/tj20185584/tomcat

阿里云镜像服务

产品与服务->弹性计算->容器镜像服务->命名空间(创建)->镜像仓库(创建)

然后在镜像仓库页面中点击“管理”,查看操作指南即可

添加映射卷

先停止容器

1
docker stop 容器名称

停止docker服务

1
sudo snap stop docker # 我的树莓派用的是snap安装

查找config.v2.json文件

1
2
3
4
# snap
cd /var/snap/docker/common/var-lib-docker/containers/容器ID
# 正常
cd /var/lib/docker/containers/容器ID/

修改MountPoints下的配置,要注意bind和volume的区别,bind是容器以宿主机文件夹为准;

而volume是 ① 宿主有数据时,以宿主机为准 ②宿主无数据,从容器复制过来,再以宿主机为准。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
"/var/www/html/pan": {
"Source": "/media/banana", // 宿主机路径
"Destination": "/var/www/html/pan", // 容器内路径
"RW": true,
"Name": "",
"Driver": "",
"Type": "bind",
"Propagation": "rprivate",
"Spec": {
"Type": "bind",
"Source": "/media/banana",
"Target": "/var/www/html/pan"
},
"SkipMountpointCreation": false
}

启动docker服务

1
sudo snap start docker

启动容器

1
docker start 容器ID

五. SpringBoot打包Docker镜像

1.将项目打包 maven package

2.在idea中安装Docker插件

3.在target文件夹内编写Dockerfile文件

1
2
3
4
5
6
7
8
9
FROM java:8

COPY *.jar /app.jar

CMD ["--server.port=8080"]

EXPOSE 8080

ENTRYPOINT ["java","-jar","/app.jar"]

4.将jar包(或war包)和Dockerfile上传至服务器

5.打包镜像

1
docker build -t 镜像名 .

6.生成容器并运行

1
docker run -d -P --name 容器名 镜像名

六. Mac上的容器访问问题

在macOS上的Docker无法通过容器IP直接访问,因为系统问题,造成Docker底层实现有差距,

原因参考:https://blog.csdn.net/luo_cs_dn/article/details/122880902

解决方法是安装docker-connector:

1
2
3
4
5
6
7
8
9
10
11
12
# 参考 https://github.com/wenjunxiao/mac-docker-connector
brew tap wenjunxiao/brew
brew install docker-connector

# 把docker的网络写入connector的配置文件,如果后面新创建了网络需要手动加入或重新执行下列命令
docker network ls --filter driver=bridge --format "{{.ID}}" | xargs docker network inspect --format "route {{range .IPAM.Config}}{{.Subnet}}{{end}}" >> "$(brew --prefix)/etc/docker-connector.conf"

sudo brew services start docker-connector

docker pull wenjunxiao/mac-docker-connector

docker run -it -d --restart always --net host --cap-add NET_ADMIN --name connector wenjunxiao/mac-docker-connector

然后就可以通过IP地址访问容器了。

七. Docker Compose部署微服务案例

Docker Compose可以基于Compose文件快速部署分布式应用,无需一个个手动创建和运行容器。

下面以部署gateway、order-service和user-service为例,目录结构如下图。

目录结构

其中gateway、order-service、user-service 这三个文件夹中都有一个Dockerfile文件,内容如下:

1
2
3
FROM java:8-alpine
COPY ./app.jar /tmp/app.jar
ENTRYPOINT java -jar /tmp/app.jar

后面只要将打包好的微服务jar包命名为app.jar放进去即可。

然后是最外层的docker-compose.yml文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
version: "3.2"

services:
nacos:
image: nacos/nacos-server
environment:
MODE: standalone
ports:
- "8848:8848"
mysql:
image: mysql:5.7.25
environment:
MYSQL_ROOT_PASSWORD: 123
volumes:
- "$PWD/mysql/data:/var/lib/mysql"
- "$PWD/mysql/conf:/etc/mysql/conf.d/"
userservice:
build: ./user-service
orderservice:
build: ./order-service
gateway:
build: ./gateway
ports:
- "10010:10010"

打包时要注意把项目的数据库、nacos地址都命名为docker-compose中的服务名。

然后在cloud-demo目录下执行:

1
2
3
4
docker-compose up -d

# 如果出现nacos太晚启动导致其他服务启动失败的情况,需要重启
docker-compose restart gateway userservice orderservice

八. 私有镜像仓库

搭建

首先编写docker-compose.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
version: '3.0'
services:
registry:
image: registry
volumes:
- ./registry-data:/var/lib/registry
ui:
image: joxit/docker-registry-ui:static
ports:
- 8080:80
environment:
- REGISTRY_TITLE=扎克蕉的私人仓库
- REGISTRY_URL=http://registry:5000
depends_on:
- registry

运行docker-compose up -d指令,随后访问该机器对应IP的8080端口,如下图所示。

由于本地测试没有HTTPS协议,需要配置信任地址。

Linux:vim /etc/docker/daemon.json

Mac:vim ~/.docker/daemon.json

最外层添加内容:“insecure-registries”:[“http://172.16.155.19:8080”]

然后重启Docker即可。

上传与拉取镜像

1
2
3
4
5
6
7
8
# 重命名镜像
docker tag nginx:latest 172.16.155.19:8080/nginx:1.0

# PUSH镜像
docker push 172.16.155.19:8080/nginx:1.0

# PULL镜像
docker pull 172.16.155.19:8080/nginx:1.0