Please enable Javascript to view the contents

使用Docker部署开发环境

 ·  ☕ 17 分钟

TODO: 此文档还需完善请留言或联系作者

部署 Tomcat

在拉取 tomcat 镜像的时候,可能搞不明白为什么会有如此之多的tag?这里我们先了解一下,该镜像相关的Variants(变体)的含义:

  • tomcat:<version>:如果您不确定您的需求是什么,您可能想要使用这个。它被设计为既可以用作丢弃容器(安装源代码并启动容器来启动应用程序),也可以用作构建其他图像的基础。
  • tomcat:slim:此映像不包含默认tag中包含的公共包,仅包含运行tomcat所需的最小包。除非您在仅部署tomcat映像并且存在空间限制的环境中工作,否则我们强烈建议您使用此库的默认镜像(即上一个镜像)。 (slim:瘦)
  • tomcat:alpine 此镜像基于流行的Alpine Linux项目 。(不了解什么是 Alpine Linux Project,不下这个版本)
  • tomcat:<version>-jre*:这个又是什么意思?查看Dockerfile文件,似乎所有文件都是FROM openjdk:*-jre 开头,那么所有镜像都是以openjdk作为基础镜像的?

还是没搞懂,这里选择 8.5.32

docker pull tomcat:8.5.32

运行容器

1
2
3
# 记得修改 tag
$ docker run -it --rm -p 8888:8080 tomcat:tag
# You can then go to http://localhost:8888 or http://host-ip:8888 in a browser

tomcat容器的使用:

部署 MySQL / MariaDB

MariaDB 与 MySQL 在配置上几乎是一样的。

对于mysql 5 ,设置字符集、排序方式和忽略大小写:

1
2
docker run --name some-mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag --character-set-server=utf8 --collation-server=utf8_unicode_ci --lower-case-table-names=1
docker run --name some-mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --lower-case-table-names=1

对于mysql 8 ,设置字符集和排序方式:

1
docker run --name some-mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci

mysql 8 配置忽略大小写:

  • 先使用上面的命令创建并运行容器 some-mysql
  • 在主机中创建配置文件,比如 /root/docker/mysql8/conf.d/config-file.cnf,文件内容如下:
[mysqld]
  lower_case_table_names = 1
  • 使用下面的命令将该文件复制到容器中
1
docker cp /root/docker/mysql8/conf.d/config-file.cnf some-mysql:/etc/mysql/conf.d/
  • 停止容器
  • 删除数据目录,比如删除 /var/lib/mysql
  • 重启容器

创建数据库dumps:

使用 docker exec 并在同一个容器中运行该dump工具

1
$ docker exec some-mysql sh -c 'exec mysqldump --all-databases -uroot -p"$MYSQL_ROOT_PASSWORD"' > /some/path/on/your/host/all-databases.sql

还原SQL文件中的数据:

用于恢复数据。 可以将 docker exec 命令与-i 标志一起使用:

1
$ docker exec -i some-mysql sh -c 'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD"' < /some/path/on/your/host/all-databases.sql

环境变量:

在启动 MySQL 映像时,可以通过在 docker run 命令行上传递一个或多个环境变量来调整 MySQL 实例的配置。 请注意,如果您使用已经包含数据库的数据目录启动容器,则下面的任何变量都不会产生任何影响: 任何预先存在的数据库在容器启动时都将保持不变。

如果您启动 MYSQL 容器实例时使用的数据目录已经包含了一个数据库 (特别是 mysql 子目录) ,那么在运行命令行中应该省略 $MYSQL_ROOT_PASSWORD 变量;在任何情况下,它都将被忽略,并且不会以任何方式更改先前存在的数据库。

  • MYSQL_ROOT_PASSWORD : 此变量是 强制性 的,它指定将为 MySQL root 超级用户帐户设置的密码。
  • MYSQL_DATABASE :此变量是可选的,并允许您指定要在映像启动时创建的数据库的名称。 如果提供了用户 / 密码(见下文) ,那么该用户将被授予对该数据库的超级用户访问权(对应于 GRANT ALL)。
  • MYSQL_USER, MYSQL_PASSWORD :这些变量是可选的,用于创建新用户和设置该用户的密码。 此用户将被授予 MYSQL database 变量指定的数据库的超级用户权限(见上文)。 创建用户需要这两个变量。
  • MYSQL_RANDOM_ROOT_PASSWORD :随机根密码。这是一个可选变量。 设置为 yes 以便为 root 用户生成一个随机的初始密码(使用 pwgen)。 生成的 ROOT 密码将被打印到 stdout (GENERATED ROOT PASSWORD: …..)
  • MYSQL_ONETIME_PASSWORD :一次性密码。设置当 root 用户一旦初始化完成,用户将过期为过期,迫使第一次登录时更改密码。 注意: 这个特性只支持 MySQL 5.6 + 版本。

Docker Secrets:

作为通过环境变量传递敏感信息的替代方法,_FILE 可以附加到前面列出的环境变量,从而使初始化脚本从容器中存在的文件中加载这些变量的值。特别是,这可以用于从 /run/secrets/<secret_name> 中加载密码。比如:

1
$ docker run --name some-mysql -e MYSQL_ROOT_PASSWORD_FILE=/run/secrets/mysql-root -d mysql:tag

目前,只支持 MYSQL_ROOT_PASSWORD, MYSQL_ROOT_HOST, MYSQL_DATABASE, MYSQL_USERMYSQL_PASSWORD

mysql Dockerfile 部分内容:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
FROM debian:stretch-slim

ENV MYSQL_VERSION 8.0.19-1debian9
RUN apt-get install -y mysql-community-client="${MYSQL_VERSION}" mysql-community-server-core="${MYSQL_VERSION}"
VOLUME /var/lib/mysql
# Config files
COPY config/ /etc/mysql/
COPY docker-entrypoint.sh /usr/local/bin/
RUN ln -s usr/local/bin/docker-entrypoint.sh /entrypoint.sh # backwards compat
ENTRYPOINT ["docker-entrypoint.sh"]

EXPOSE 3306 33060
CMD ["mysqld"]

部署 CentOS

Tag的选择:

The CentOS Project offers regularly updated images for all active releases. These images will be updated monthly or as needed for emergency fixes. These rolling updates(滚动更新) are tagged with the major version number only. For example:

建议pull的image:

docker pull centos:6
docker pull centos:7

tag 带有小数点的版本不进行滚动更新维护

部署 Oracle Db 11g

Oracle 11g

wnameless/docker-oracle-xe-11g: Dockerfile of Oracle Database Express Edition 11g Release 2

添加到 javaee 网络

docker run --name oracle11g -d -p 49161:22 -p 1522:1521 -p 49163:8080 -v /oracle11g-data/:/u01/app/oracle/oradata/oracle11g-data/ -e ORACLE_ALLOW_REMOTE=true wnameless/oracle-xe-11g

使用下面的语句启动容器:

docker run --name oracle11g -d -p 1522:1521 -p 49163:8080 --network javaee -v G:/Docker/JavaEERuntime/oracle11g/data:/u01/app/oracle/oradata/oracle11g-data/ -e ORACLE_ALLOW_REMOTE=true wnameless/oracle-xe-11g

启动容器后要等1~2分钟Oracle监听器才开启,所以等一下再连接。

使用jdbc连接数据库:

url: 注意端口这里并不是 默认的 1521

jdbc:oracle:thin:@//127.0.0.1:1522
jdbc:oracle:thin:@localhost:1522

使用非DBA用户连接(需选择system用户)

hostname: localhost
port: 49161
sid: xe
username: system
password: oracle

sid : xe 其中 xe 也是当前实例名称,在单机模式xe也就是数据库名称。

以dba身份登录: 用户sys和密码 oracle

如果选择sys用户则需勾选 as SYSDBA

在浏览器中访问:

url:127.0.0.1:49163

用户和密码: systemoracle

创建表空间:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
-- 创建表空间1
create tablespace itheima
datafile '/u01/app/oracle/oradata/oracle11g-data/itheima.dbf'
size 20M  --初始化大小
autoextend on  --自动扩展
next 10M;  --每次添加10M

-- 创建表空间2
create tablespace itheima
  datafile '/u01/app/oracle/oradata/oracle11g-data/itheima.dbf'
size 10M
extent management local autoallocate;

--  本地化管理方式创建,
-- extent management local autoallocate是设置当表空间大小已满时,用自动管理的方式扩展表空间。

创建表空间时,如果提示找不到目录,则需要进入容器创建对应的目录。

创建用户:

1
2
create user itheima identified by fan123
  default tablespace itheima;

为用户授权:

1
grant connect, resource, dba to itheima;

在容器中使用sqlplus:(参考了下文的Oracle 12c)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
➜  ~ docker exec -it 5c02b9 bash
[email protected]:/# netstat -nlpt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      -
tcp        0      0 0.0.0.0:1521            0.0.0.0:*               LISTEN      -
tcp        0      0 127.0.0.11:36569        0.0.0.0:*               LISTEN      -
tcp        0      0 0.0.0.0:34780           0.0.0.0:*               LISTEN      -
[email protected]:/# su oracle
[email protected]:/$ cd $ORACLE_HOME
[email protected]:~/product/11.2.0/xe$ bin/sqlplus / as sysdba

Oracle 12c

image 太大 3G,没下载完成,强行结束了,但不知如何删除?

MaksymBilenko/docker-oracle-12c: Docker image with Oracle Database 12c on board

asciicast

部署 PostgreSQL

Using Docker Compose to Install PostgreSQL 但是无法访问此网站,可以参考下面两篇文章

How to run PostgreSQL in Docker on Mac (for local development) - SaltyCrane Blog

Getting Started with PostgreSQL using Docker-Compose

部署 Redis

配置文件:

You can create your own Dockerfile that adds a redis.conf from the context into /data/, like so.,通过Dockerfile

FROM redis
COPY redis.conf /usr/local/etc/redis/redis.conf
CMD [ "redis-server", "/usr/local/etc/redis/redis.conf" ]

或者直接在 docker run中:

$ docker run -v /myredis/conf/redis.conf:/usr/local/etc/redis/redis.conf --name myredis redis redis-server /usr/local/etc/redis/redis.conf

好吧redis容器中并不存在/usr/local/etc/redis/redis.conf文件,如果需要使用配置文件,可以下载一个redis压缩包,解压后使用里面的 redis.conf 文件,然后将此配置文件随便挂载到容器的某个目录,但是要与 redis-server命令后跟的路径一致即可。

Redis客户端:

推荐使用 redis-commander ,参考:

1
2
3
4
docker run --name redis-commander -d  --network javaee \
  --env REDIS_HOSTS=javaee-redisServer,jeecg-boot_redisserver_1  \
  -p 8863:8081 \
  rediscommander/redis-commander:latest

数据持久化:

由于redis默认在内存中存储数据,如果需要将数据进行持久化就需要进行配置。

$ docker run --name some-redis -d redis redis-server --appendonly yes

If persistence is enabled, data is stored in the VOLUME /data, which can be used with --volumes-from some-volume-container or -v /docker/host/dir:/data

redis有两种数据持久化方式:

  • RDB模式 – 快照模式 。RDB是默认开启的,就是配置文件中的 save 900 1部分(如果有配置文件)。Redis会定时把内存中的数据备份,生成"快照文件”。文件名称是dump.rdb,默认被保存在了Redis的安装目录里。

  • AOF模式 。AOF需要手动配置开启 。可在配置文件中开启:

    appendonly yes                        #默认是no,未开启AOF。设置为yes表示开启AOF模式。
    appendfilename "appendonly.aof"    #默认生成的AOF文件名称
    

    或通过相关选项开启:redis-server --appendonly yes

感觉根据redis的使用方式,只需在运行时能够进行持久化即可,而无需挂载数据卷

示例:

1
2
3
docker run --name redisServer -d -p 6379:6379  redis redis-server

docker run -it --link redisServer:redis --rm  redis redis-cli -h redis -p 6379

部署 Elasticsearch

library/elasticsearch - Docker Hub

Install Elasticsearch with Docker - Elasticsearch Reference 6.4

1
docker pull elasticsearch
docker run -itd -p 9200:9200 -p 9300:9300 -v /opt/data/elasticsearch/logs:/usr/share/elasticsearch/logs -v /opt/data/elasticsearch/data:/usr/share/elasticsearch/data --name mylasticsearch -e "discovery.type=single-node" elasticsearch
# 运行下面的命令会报java异常
docker run -d -p 9200:9200 -p 9300:9300 -v /opt/data/elasticsearch/logs:/usr/share/elasticsearch/logs -v /opt/data/elasticsearch/data:/usr/share/elasticsearch/data -v /opt/data/elasticsearch/plugins:/usr/share/elasticsearch/plugins -v /opt/data/elasticsearch/config:/usr/share/elasticsearch/config --name es -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms512m -Xmx512m" elasticsearch
# 同时限制jvm内存
docker run -d -p 9200:9200 -p 9300:9300 --name es -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms512m -Xmx512m" elasticsearch

实时查看某容器的log:

docker logs -f 容器名/id

管理工具/插件

docker中安装elasticsearch-head: 浏览器输入 host-ip:9100 访问该插件 (推荐chrome插件)

1
docker run -d --name es_admin -p 9100:9100 mobz/elasticsearch-head

部署kibana

docker run -p 5601:5601 -e "ELASTICSEARCH_URL=http://172.17.0.2:9200" --name kibana --network host -d kibana:5.6.12

172.17.0.2 是 ES容器的地址。

报如下错误:WARNING: Published ports are discarded when using host network mode

但好像没有影响使用。

Elasticsearch: 权威指南 - Elastic

elasticsearch插件大全(不断更新) - 云端分布式搜索技术

ik 分词器插件

需要下载对应版本的 ik 分词器。

下载地址:Releases · medcl/elasticsearch-analysis-ik

安装方法见其 github上的readme.md

  1. 解压elasticsearch-analysis-ik-xx 后,将文件夹拷贝到elasticsearch-xx\plugins下,并重命名文件夹为ik
  2. 重新启动ElasticSearch,即可加载IK分词器

ik 分词器版本与es版本不对应报错:

org.elasticsearch.bootstrap.StartupException: java.lang.IllegalArgumentException: plugin [analysis-ik] is incompatible with version [5.6.12]; was designed for version [5.6.11]

但是并没有对应的 5.6.12 版的 ik分词器,可以尝试修改 ik分词器下的 plugin-descriptor.properties 文件,将所有的 5.6.11 都改为 5.6.12

测试:

# IK提供了两个分词算法ik_smart 和 ik_max_word
# 最小切分
http://192.168.25.129:9200/_analyze?analyzer=ik_smart&pretty=true&text=我是程序员
# 最细切分
http://192.168.25.129:9200/_analyze?analyzer=ik_max_word&pretty=true&text=我是程序员

NoNodeAvailableException 错误

在Java代码中连接时出现错误:

NoNodeAvailableException[None of the configured nodes are available:

查看log日志发现:

[2018-11-02T07:03:56,627][INFO ][o.e.n.Node               ] [l1tnBgE] starting ...
[2018-11-02T07:03:56,934][INFO ][o.e.t.TransportService   ] [l1tnBgE] publish_address {127.0.0.1:9300}, bound_addresses {127.0.0.1:9300}
[2018-11-02T07:04:00,151][INFO ][o.e.c.s.ClusterService   ] [l1tnBgE] new_master {l1tnBgE}{l1tnBgEeTWig7WULclcimQ}{dvOVG91GT--NfTl_iVnfzQ}{127.0.0.1}{127.0.0.1:9300}, reason: zen-disco-elected-as-master ([0] nodes joined)[, ]
[2018-11-02T07:04:00,231][INFO ][o.e.h.n.Netty4HttpServerTransport] [l1tnBgE] publish_address {172.17.0.2:9200}, bound_addresses {0.0.0.0:9200}

可以发现9300和9200端口的地址是不一样的

publish_address {127.0.0.1:9300}

publish_address {172.17.0.2:9200}

再查看容器中config下的elasticsearch.yml配置文件:

# cat elasticsearch.yml
http.host: 0.0.0.0
# Uncomment the following lines for a production cluster deployment
#transport.host: 0.0.0.0
#discovery.zen.minimum_master_nodes: 1

会发现 并没有看到他人所说的 network.host: 0.0.0.0 (将其配置为0.0.0.0意为允许外部访问),这里它被分成了 http.host 和 transport.host 两个配置项,并且 transport.host 默认是被注释掉的!! 所以我们需要取消 transport.host 的注释,方法是在外部新建一个 elasticsearch.yml 然后再cp到容器内。

 # 一个cp 示例:这里是从es容器中复制文件到主机 (调换一下即可改变复制方向)
 docker cp es:/usr/share/elasticsearch/config  /opt/data/elasticsearch

最后查看系统的相应端口有没有开放

Docker下 Dubbo开发

ZooKeeper

library/zookeeper - Docker Hub

Zookeeper应用介绍与安装部署 - 简书

单机模式

zoo.cfg配置

1
2
3
4
ticketTime=2000
clientPort=2181
dataDir=/opt/zookeeper/data
dataLogDir=/opt/zookeeper/logs

集群模式

zoo.cfg配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
ticketTime=2000
clientPort=2181
dataDir=/opt/zookeeper/data
dataLogDir=/opt/zookeeper/logs

initLimit=10
syncLimit=5
server.1=master:2888:3888
server.2=slave01:2888:3888
server.3=slave02:2888:3888

由上面的配置可知,需要挂载的有 zoo.cfg 配置文件、保存数据的data目录、保存log的logs目录。

1
docker run --name temp-zookeeper --rm -d zookeeper

先查看容器结构:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
bash-4.4# cat /conf/zoo.cfg 
clientPort=2181
dataDir=/data
dataLogDir=/datalog
tickTime=2000
initLimit=5
syncLimit=2
autopurge.snapRetainCount=3
autopurge.purgeInterval=0
maxClientCnxns=60

修改本地 conf/zoo.cfg 文件内容,然后运行容器:

1
docker run --name javaee-zookeeper -v G:/Docker/JavaEERuntime/zookeeper/data:/data -v G:/Docker/JavaEERuntime/zookeepe/conf:/conf -v G:/Docker/JavaEERuntime/zookeeper/logs:/datalog -p 2181:2181 --network javaee -d zookeeper:latest

dubbo-admin

监控与管理dubbo服务

老师给的 dubbo-admin.war 包无法在 Docker中的tomcat上运行,

从网上下载的Dubbo源码通过编码后得到的war包或者下载的war包,默认不支持JDK1.8,在tomcat中运行会报错

解决方式一: 直接在Docker Hub上寻找现有dubbo-admin镜像(完美解决)

docker pull chenchuxin/dubbo-admin

解决方式二:寻找可用的 war 包 (tomcat还是报异常

可以寻找支持 JDK1.8 的 Dubbo-admin war包,比如:https://pan.baidu.com/s/1jpq8tD7DlKZItLpgyx5lfA 密码:6w7d

Docker下dubbo开发,三部曲之二:本地环境搭建 - CSDN博客

docker安装zookeeper和dubbo-admin - CSDN博客

Dubbo教程(二)—-Dubbo-admin管理平台搭建 - CSDN博客

Docker+Spring+Dubbo+ZooKeeper完成服务化RPC实验 - CSDN博客

注意,dubbo-admin有些是tomcat7有些是tomcat8的

并且可能和 jdk 版本也有关系。

FastDFS

第一次尝试

使用 season/fastdfs (不确定其是否整合了Nginx,因该时没有,怕麻烦直接使用了第二种方法)

1
2
3
4
5
6
docker run --name javaee-zookeeper -v G:/Docker/JavaEERuntime/zookeeper/data:/data -v G:/Docker/JavaEERuntime/zookeepe/conf:/conf -v G:/Docker/JavaEERuntime/zookeeper/logs:/datalog -p 2181:2181 --network javaee -d zookeeper:latest

# tracker
docker run -dti --name fastdfs-trakcer -v G:/Docker/JavaEERuntime/fastDFS/tracker/data:/fastdfs/tracker/data --network javaee season/fastdfs tracker

docker run -dti --name fastdfs-trakcer -v G:/Docker/JavaEERuntime/fastDFS/tracker/data:/fastdfs/tracker/data -p 22122:22122 --network javaee season/fastdfs
  • port

tracker default port is 22122

  • base_path

you should map the path: /fastdfs/tracker/data to keep the data

安装成功后进入/etc/fdfs 目录:
拷贝一份新的 tracker 配置文件:
cp tracker.conf.sample tracker.conf
修改 tracker.conf
vi tracker.conf
base_path=/home/yuqing/FastDFS
改为:
base_path=/home/FastDFS
1
2
3
4
5
6
#storage
docker run -ti --name fastdfs-storage -v ~/storage_data:/fastdfs/storage/data -v ~/store_path:/fastdfs/store_path --net=host -e TRACKER_SERVER:192.168.1.2:22122 season/fastdfs storage

docker run --name fastdfs-storage -v G:/Docker/JavaEERuntime/fastDFS/storage/data:/fastdfs/storage/data -v G:/Docker/JavaEERuntime/fastDFS/storage/store_path:/fastdfs/store_path --network javaee -e TRACKER_SERVER:fastdfs-trakcer:22122 season/fastdfs

docker run --name fastdfs-storage -v G:/Docker/JavaEERuntime/fastDFS/storage/base_data:/fastdfs/storage/data -v G:/Docker/JavaEERuntime/fastDFS/storage/store_path0:/fastdfs/store_path --network javaee -e TRACKER_SERVER:fastdfs-trakcer:22122 season/fastdfs
  • storage_data

equal to “base_path” in store.conf

  • store_path

equal to “store_path0” in store.conf

  • TRACKER_SERVER

tracker address

补充

  • log (所以不用指定log目录)

I redirect FastDFS’s log file to container’s stdout, so, its easy to collect log.

  • use your config file

FastDFS config files is in: /fdfs_conf

安装成功后进入/etc/fdfs 目录:
拷贝一份新的 storage 配置文件:
cp storage.conf.sample storage.conf
修改 storage.conf
vi storage.conf
group_name=group1
base_path=/home/yuqing/FastDFS 改为:base_path=/home/FastDFS
store_path0=/home/yuqing/FastDFS 改为:store_path0=/home/FastDFS/fdfs_storage
#如果有多个挂载磁盘则定义多个 store_path,如下
#store_path1=.....
#store_path2=......
tracker_server=192.168.101.3:22122 #配置 tracker 服务器:IP
#如果有多个则配置多个 tracker
tracker_server=192.168.101.4:22122

第二次尝试

使用整合了nginx的fastdfs : ygqygq2/fastdfs-nginx

1
2
3
4
5
6
7
docker run -dti --network=host --name tracker -v /var/fdfs/tracker:/var/fdfs ygqygq2/fastdfs-nginx tracker

docker run -dti --network=host --name storage0 -e TRACKER_SERVER=10.1.5.85:22122 -v /var/fdfs/storage0:/var/fdfs ygqygq2/fastdfs-nginx storage

docker run -dti --network=host --name storage1 -e TRACKER_SERVER=10.1.5.85:22122 -v /var/fdfs/storage1:/var/fdfs ygqygq2/fastdfs-nginx storage

docker run -dti --network=host --name storage2 -e TRACKER_SERVER=10.1.5.85:22122 -e GROUP_NAME=group2 -e PORT=22222 -v /var/fdfs/storage2:/var/fdfs ygqygq2/fastdfs-nginx storage

修改

1
2
3
4
5
6
7
docker run -dti --network=javaee --name tracker -v G:/Docker/JavaEERuntime/fastDFS/tracker/data:/var/fdfs  -p 22122:22122 ygqygq2/fastdfs-nginx tracker

docker run -dti --network=javaee --name storage0 -e TRACKER_SERVER=tracker:22122 -v G:/Docker/JavaEERuntime/fastDFS/storage/store_path0:/var/fdfs ygqygq2/fastdfs-nginx storage

docker run -dti --network=javaee --name storage1 -e TRACKER_SERVER=tracker:22122 -v G:/Docker/JavaEERuntime/fastDFS/storage/store_path1:/var/fdfs ygqygq2/fastdfs-nginx storage

docker run -dti --network=javaee --name storage2 -e TRACKER_SERVER=tracker:22122 -e GROUP_NAME=group2 -e PORT=22222 -v G:/Docker/JavaEERuntime/fastDFS/storage/store_path2:/var/fdfs ygqygq2/fastdfs-nginx storage

tracker log:

[2018-09-26 15:41:02] INFO - file: tracker_relationship.c, line: 394, selecting leader...
[2018-09-26 15:41:02] INFO - file: tracker_relationship.c, line: 412, I am the new tracker leader 172.18.0.2:22122

storage0 log:

[2018-09-26 15:41:03] INFO - file: storage_func.c, line: 257, tracker_client_ip: 172.18.0.3, my_server_id_str: 172.18.0.3, g_server_id_in_filename: 50336428
[2018-09-26 15:41:03] INFO - file: tracker_client_thread.c, line: 310, successfully connect to tracker server 172.18.0.2:22122, as a tracker client, my ip is 172.18.0.3
[2018-09-26 15:41:33] INFO - file: tracker_client_thread.c, line: 1263, tracker server 172.18.0.2:22122, set tracker leader: 172.18.0.2:22122

两者可以连接成功,但是java无法使用该地址连接

connect to server 172.18.0.2:22122 fail
java.net.ConnectException: Connection timed out: connect
  at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
  at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85)
  at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
  at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
  at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
  at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
  at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
  at java.net.Socket.connect(Socket.java:589)
  at org.csource.fastdfs.TrackerGroup.getConnection(TrackerGroup.java:47)
  at org.csource.fastdfs.TrackerGroup.getConnection(TrackerGroup.java:72)
  at org.csource.fastdfs.TrackerClient.getConnection(TrackerClient.java:58)
  at cn.itcast.demo.FastDFSDemo.main(FastDFSDemo.java:14)
connect to server 172.18.0.2:22122 fail
java.net.ConnectException: Connection timed out: connect
  at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
  at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85)
  at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
  at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
  at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
  at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
  at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
  at java.net.Socket.connect(Socket.java:589)
  at org.csource.fastdfs.TrackerGroup.getConnection(TrackerGroup.java:47)
  at org.csource.fastdfs.TrackerGroup.getConnection(TrackerGroup.java:72)
  at org.csource.fastdfs.TrackerClient.getConnection(TrackerClient.java:58)
  at org.csource.fastdfs.TrackerClient.getStoreStorage(TrackerClient.java:91)
  at org.csource.fastdfs.StorageClient.newWritableStorageConnection(StorageClient.java:1912)
  at org.csource.fastdfs.StorageClient.do_upload_file(StorageClient.java:702)
  at org.csource.fastdfs.StorageClient.upload_file(StorageClient.java:163)
  at org.csource.fastdfs.StorageClient.upload_file(StorageClient.java:131)
  at org.csource.fastdfs.StorageClient.upload_file(StorageClient.java:113)
  at cn.itcast.demo.FastDFSDemo.main(FastDFSDemo.java:20)
Exception in thread "main" java.lang.Exception: getStoreStorage fail, errno code: 0
  at org.csource.fastdfs.StorageClient.newWritableStorageConnection(StorageClient.java:1915)
  at org.csource.fastdfs.StorageClient.do_upload_file(StorageClient.java:702)
  at org.csource.fastdfs.StorageClient.upload_file(StorageClient.java:163)
  at org.csource.fastdfs.StorageClient.upload_file(StorageClient.java:131)
  at org.csource.fastdfs.StorageClient.upload_file(StorageClient.java:113)
  at cn.itcast.demo.FastDFSDemo.main(FastDFSDemo.java:20)

将ip地址改为本地回环地址后出现:

Exception in thread "main" java.net.ConnectException: Connection timed out: connect
  at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
  at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85)
  at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
  at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
  at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
  at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
  at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
  at java.net.Socket.connect(Socket.java:589)
  at org.csource.fastdfs.ClientGlobal.getSocket(ClientGlobal.java:107)
  at org.csource.fastdfs.StorageServer.<init>(StorageServer.java:45)
  at org.csource.fastdfs.TrackerClient.getStoreStorage(TrackerClient.java:158)
  at org.csource.fastdfs.StorageClient.newWritableStorageConnection(StorageClient.java:1912)
  at org.csource.fastdfs.StorageClient.do_upload_file(StorageClient.java:702)
  at org.csource.fastdfs.StorageClient.upload_file(StorageClient.java:163)
  at org.csource.fastdfs.StorageClient.upload_file(StorageClient.java:131)
  at org.csource.fastdfs.StorageClient.upload_file(StorageClient.java:113)
  at cn.itcast.demo.FastDFSDemo.main(FastDFSDemo.java:20)

docker run -dti --network=host --name tracker ygqygq2/fastdfs-nginx tracker

docker run -dti --network=host --name storage0 -e TRACKER_SERVER=10.1.5.85:22122  ygqygq2/fastdfs-nginx storage

docker run -dti --network=host --name storage1 -e TRACKER_SERVER=10.1.5.85:22122  ygqygq2/fastdfs-nginx storage

docker run -dti --network=host --name storage2 -e TRACKER_SERVER=10.1.5.85:22122 -e GROUP_NAME=group2 -e PORT=22222  ygqygq2/fastdfs-nginx storage

######

docker run -dti --network=host --name storage0 -e TRACKER_SERVER=tracker:22122  ygqygq2/fastdfs-nginx storage

docker run -dti --network=host --name storage1 -e TRACKER_SERVER=tracker:22122  ygqygq2/fastdfs-nginx storage

docker run -dti --network=host --name storage2 -e TRACKER_SERVER=tracker:22122 -e GROUP_NAME=group2 -e PORT=22222  ygqygq2/fastdfs-nginx storage

上面修改的命令中,需要改进的地方是:G:/Docker/JavaEERuntime/fastDFS/storage/store_path0 不要写成

store_path0 ,直接是 storage0 就行,因为该目录下会自动创建 data 和 log 目录

JavaEE

先创建javaee网络:

1
docker network create -d bridge javaee

再运行各容器:

 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
docker run --name javaee-mysql5.5 -v G:/Docker/JavaEERuntime/mysql5.5/data:/var/lib/mysql -p 3306:3306 --network javaee -e MYSQL_ROOT_PASSWORD=fan123 -d mysql:5.5.60 --character-set-server=utf8 --collation-server=utf8_unicode_ci --lower-case-table-names=1

docker run --name javaee-tomcat -v G:/Docker/JavaEERuntime/tomcat-8.5/webapps:/usr/local/tomcat/webapps -v G:/Docker/JavaEERuntime/tomcat-8.5/conf:/usr/local/tomcat/conf -p 8080:8080 --network javaee -d tomcat:8.5.32

docker run --name javaee-nginx -v G:/Docker/JavaEERuntime/nginx/html:/usr/share/nginx/html -v G:/Docker/JavaEERuntime/nginx/nginx.conf:/etc/nginx/nginx.conf -p 80:80 --network javaee -d nginx:latest


docker run --name javaee-redis  -v G:/Docker/JavaEERuntime/redis/redis.conf:/usr/local/etc/redis/redis.conf -v G:/Docker/JavaEERuntime/redis/data:/data -p 6379:6379 --network javaee -d redis:latest redis-server /usr/local/etc/redis/redis.conf

# ---------------------------------------

docker run --name javaee-zookeeper -v G:/Docker/JavaEERuntime/zookeeper/data:/data -v G:/Docker/JavaEERuntime/zookeepe/conf:/conf -v G:/Docker/JavaEERuntime/zookeeper/logs:/datalog -p 2181:2181 --network javaee -d zookeeper:latest


## 使用 javaee-zookeeper:2181 代替 127.0.0.1:2181 才能连接成功
docker run --name dubbo-admin \
-p 8888:8080 \
-e dubbo.registry.address=zookeeper://javaee-zookeeper:2181 \
-e dubbo.admin.root.password=root \
-e dubbo.admin.guest.password=guest \
--network javaee -d \
chenchuxin/dubbo-admin


docker run --name javaee-tomcat7-01 -v G:/Docker/JavaEERuntime/tomcat-7/webapps:/usr/local/tomcat/webapps -v G:/Docker/JavaEERuntime/tomcat-7/conf:/usr/local/tomcat/conf -p 8701:8080 --network javaee -d tomcat:7
webapps目录和 conf目录非原生,还需要更改

下面已经运行在阿里云主机上:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
docker network create -d bridge javaee

docker run --name javaee-mysql5.5 -v /opt/docker/mysql5.5/data:/var/lib/mysql -p 3305:3306 -e MYSQL_ROOT_PASSWORD=R6943Vb7 --network javaee -d mysql:5.5.60 --character-set-server=utf8 --collation-server=utf8_unicode_ci --lower-case-table-names=1

docker run --name javaee-redisServer --network javaee -d -p 63791:6379  redis


docker run --name javaee-redis-commander -d  --network javaee \
  --env REDIS_HOSTS=javaee-redisServer \
  -p 8863:8081 \
  rediscommander/redis-commander:latest

docker run --name javaee-zookeeper  -p 21810:2181 --network javaee -d zookeeper:latest

docker run --name javaee-dubbo-admin \
-p 8826:8080 \
-e dubbo.registry.address=zookeeper://javaee-zookeeper:2181 \
-e dubbo.admin.root.password=fan123 \
-e dubbo.admin.guest.password=guest \
--network javaee -d \
chenchuxin/dubbo-admin


docker run --name javaee-oracle11g -d -p 41521:1521 -p 49163:8080 --network javaee -e ORACLE_ALLOW_REMOTE=true wnameless/oracle-xe-11g

link转network示例:阿里云主机地址需改为实际地址

# 服务器
$ docker run --rm --name some-redis -d redis

# 客户端
$ docker run -it --link some-redis:redis --rm redis redis-cli -h redis -p 6379

################

# 使用network的方式代替 link,并且更改了一下与主机(47.107.182.8)的映射端口
docker run --name javaee-redisServer --network javaee -d -p 63791:6379  redis
# 在同一主机内,由于他们属于同一docker网络所以,端口号使用 6379 而无需使用 63791
docker run -it --network javaee --rm redis redis-cli -h javaee-redisServer -p 6379

# 在其它主机,进行远程连接
docker run -it --rm redis redis-cli -h 47.107.182.8 -p 63791


# Zk
docker run --name javaee-zookeeper  -p 21810:2181 --network javaee -d zookeeper:latest

# zk-cli  (-it表示已交互式方式运行,zookeeper表示使用最新镜像 zkCli.sh表示运行该脚本 -server指定服务主机)
docker run -it --rm --network javaee zookeeper zkCli.sh -server javaee-zookeeper

可以使用此方式连接 redis: 不建议使用 –link

1
2
3
4
5
6
7
8
9
# 使用下面的方法不行,提示他们不属于同一个网络
#docker run -it --link javaee-redis:redis --rm redis redis-cli -h redis -p 6379

# 使用下面的命令,提示无法连接到127.0.0.1 ( Could not connect to Redis at 127.0.0.1:6379: Connection refused)
# docker run -it --name redis-cli --network javaee redis:latest redis-cli

# 使用下面的命令,明确为 credis-cli 指定 host 和 端口
# # 这里 -h -p 选项是传递给 redis-cli 用的,并非给 docker run 使用
docker run -it --name redis-cli --network javaee redis:latest redis-cli  -h javaee-redis -p 6379

此命令输出:

1
2
$ docker run -it --name redis-cli --network javaee redis:latest redis-cli  -h javaee-redis -p 6379
javaee-redis:6379>

GoogleContainerTools: Jib

Build container images for your Java applications. 谷歌开源的 Java 应用容器生成工具,不用写 Dockerfile,构造过程中自动生成一个 Docker 容器。

Jeecg-Boot

JeecgBoot 开发文档 · 看云,这里使用 docker-compose

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
25
26
27
version: '3'

services:
  mysql57:
    image: mysql:5.7
    command: --character-set-server=utf8 --collation-server=utf8_unicode_ci --lower-case-table-names=1
    networks: 
      - jeecgboot
    restart: always
    volumes:
      - /root/docker/mysql/jbdata:/var/lib/mysql
    ports:
       - "3305:3306"
    environment: 
       MYSQL_ROOT_PASSWORD: jdb57
       # MYSQL_DATABASE: jeecgboot
       #MYSQL_USER: jeecgboot
       #MYSQL_PASSWORD: jbmsql57
  redisserver:
    image: redis
    networks: 
      - jeecgboot
    restart: always
    ports: 
      - "6379:6379"
networks:
  jeecgboot:
1
2
$ docker volume create portainer_data
$ docker run -d -p 8000:8000 -p 9000:9000 --name portainer --restart always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer

感觉 portainer 依靠的是 docker.sock ,并不需要将其添加到某个具体的网络

1
2
3
# docker network connect multi-host-network my_container1
docker network ls
docker network connect jeecg-boot_jeecgboot portainer
1
2
3
4
5
# 必须在同一网络内(还没有测试使用两个 --network)
docker run --name redis-commander -d  --network javaee --network jeecg-boot_jeecgboot \
  --env REDIS_HOSTS=javaee-redisServer,jeecg-boot_redisserver_1  \
  -p 8863:8081 \
  rediscommander/redis-commander:latest

Dockerfile:

1
2
3
4
5
FROM openjdk:7
COPY /root/docker/docker-compose/jeecg-boot/openjdk /usr/src/jeecgboot
WORKDIR /usr/src/jeecgboot
ENTRYPOINT ["java","-jar"]  # 定参
CMD ["/usr/src/jeecgboot/*.jar", ">catalina.out 2>&1"] # 变参

由于Jeecg-Boot还需要设置

  • 文件上传根目录:这里云主机路径为/root/docker/docker-compose/jeecg-boot/upload ,Java容器中的路径为 /opt/jeecg-boot/upload
  • ElasticSearch
  • 在线预览文件服务器地址配置
  • cas单点登录

Nginx 的反向代理设置:(还需要修改)

# 这里需要指定 java 的容器
proxy_pass              http://127.0.0.1:8080/jeecg-boot/;
proxy_set_header        Host 127.0.0.1;

部署 Nginx

nginx - Docker Hub

NGINX Docs | Deploying NGINX and NGINX Plus on Docker

Nginx 容器教程 - 阮一峰的网络日志

1
docker run --name some-nginx -p 8080:80 -v /some/content:/usr/share/nginx/html:ro  -v /host/path/nginx.conf:/etc/nginx/nginx.conf:ro  -d nginx

这里这个 :ro 表示只读

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# vim: set shiftwidth=2 tabstop=2 softtabstop=-1 expandtab:

version: '2'
services:
  nginx:
    image: nginx:stable-alpine
    restart: unless-stopped
    network_mode: host
    volumes:
      - /srv/nginx/nginx.conf:/etc/nginx/nginx.conf
      - /srv/nginx/conf.d:/etc/nginx/conf.d
      - /srv/nginx/html:/usr/share/nginx/html
      - /var/log/nginx:/var/log/nginx
    ports:
      - "80:80"
    environment:
      - NGINX_HOST=your.domain
      - NGINX_PORT=80

Nginx的默认配置文件路径为 /etc/nginx/nginx.conf

先运行一个临时 nginx容器,复制容器中的 Nginx 配置文件夹目录到主机的当前目录

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
$ docker run --rm --name mynginx -p 8080:80 -d nginx
$ docker container cp mynginx:/etc/nginx .
# 主机当前目录下将出现一个 nginx 目录,将此目录重命名为 conf
$ mv nginx conf
# 终止nginx容器
$ docker container stop mynginx

# 重新启动一个 nginx 容器
docker container run \
  --rm \
  --name mynginx \
  --volume "$PWD/html":/usr/share/nginx/html \
  --volume "$PWD/conf":/etc/nginx \
  -p 127.0.0.2:8080:80 \
  -d \
  nginx

日志文件:

系统中Nginx的日志文件路径为: /var/log/nginx ,但是

# 配置文件nginx.conf中的: 全局错误日志
error_log  logs/error.log;

对应了

/etc/nginx/logs/error.log

所以需要修改配置文件。

日志监控:

1
2
3
4
# 默认显示尾部10行
tail -f filename 
# 显示尾部30行
tail -f -n 30 filename  

使用Amplify监控Nginx见:(感觉有点麻烦)

nginxinc/docker-nginx-amplify: Official NGINX and Amplify Dockerfiles

监控工具有很多,比如下面的 grafana 、zabbix

dockerfile:

EXPOSE 80
STOPSIGNAL SIGTERM
CMD ["nginx", "-g", "daemon off;"]

部署 OpenJDK

openjdk - Docker Hub

使用此映像最直接的方法是将Java容器用作构建和运行时环境。在Dockerfile中,按照以下内容编写内容将编译并运行您的项目:

1
2
3
4
5
FROM openjdk:7
COPY . /usr/src/myapp
WORKDIR /usr/src/myapp
RUN javac Main.java
CMD ["java", "Main"]

然后,您可以运行并构建Docker映像:

1
2
$ docker build -t my-java-app .
$ docker run -it --rm --name my-running-app my-java-app

在Docker容器中编译您的应用:

要在Docker实例中编译但不运行您的应用程序,可以编写如下代码:

1
$ docker run --rm -v "$PWD":/usr/src/myapp -w /usr/src/myapp openjdk:7 javac Main.java

这会将当前目录作为卷添加到容器中,将工作目录设置为该卷,然后运行命令javac Main.java,该命令将告诉Java编译Main.java中的代码并将Java类文件输出到Main.class 。

对于 Maven 项目并不能简单的使用 RUN javac Main.java 来进行编译,那么该怎么做呢? maven 中的 docker 插件又是干什么的?

对于 Spring Boot 项目,我们先利用IDE将其编译打包成 jar 包。那么接下来

思路一:使用 docker run 让现有的 openjdk 容器在后台运行挂载目录中的 jar包。(但这样感觉就不好使用 docker-compose 了)

思路二:使用 Dockerfile 将 openjdk镜像 和 jar 包一起构建成为一个新的 镜像;然后在后台运行此镜像。

思路一和思路二都不涉及 编译

dockerfile:

CMD ["jshell"]

部署 registry(仓库)

Docker Registry ,registry - Docker Hub

运行本地仓库: 快速版本

1
$ docker run -d -p 5000:5000 --restart always --name registry registry:2

现在,从 Docker 内部使用它:

1
2
3
4
5
6
7
8
# Pull (or build) some image from the hub
$ docker pull ubuntu
# Tag the image so that it points to your registry
$ docker image tag ubuntu localhost:5000/myfirstimage
# Push it
$ docker push localhost:5000/myfirstimage
# Pull it back
docker pull localhost:5000/myfirstimage

Docker Registry | Docker Documentation

Registry 是一个无状态的、高度可伸缩的服务器端应用程序,它存储并允许您分发 Docker 映像。 Registry 是开源的,在许可的 Apache 许可下。

部署 node

docker-node/README.md

Run a single Node.js script:

1
$ docker run -it --rm --name my-running-script -v "$PWD":/usr/src/app -w /usr/src/app node:8 node your-daemon-or-script.js

Create a Dockerfile in your Node.js app project:

Best Practices:

Best Practices Guide

1
2
3
4
5
6
7
$ docker run \
  -e "NODE_ENV=production" \
  -u "node" \
  -m "300M" --memory-swap "1G" \
  -w "/home/node/app" \
  --name "my-nodejs-app" \
  node [script]

grafana + influxdb + cadvisor监控容器资源使用

您的鼓励是我最大的动力
alipay QR Code

Felix
作者
Felix
如无必要,勿增实体。

3

目录