Docker下打包FastDFS镜像以及上传遇到的问题

官方地址:https://github.com/happyfish100/fastdfs

一、先下载个包,然后解压(自己找个目录下载即可)

[root@localhost soft]# wget https://github.com/happyfish100/fastdfs/archive/master.zip
--2019-09-16 05:26:36--  https://github.com/happyfish100/fastdfs/archive/master.zip
Resolving github.com (github.com)... 13.250.177.223
Connecting to github.com (github.com)|13.250.177.223|:443... connected.
HTTP request sent, awaiting response... 302 Found
Location: https://codeload.github.com/happyfish100/fastdfs/zip/master [following]
--2019-09-16 05:26:37--  https://codeload.github.com/happyfish100/fastdfs/zip/master
Resolving codeload.github.com (codeload.github.com)... 13.229.189.0
Connecting to codeload.github.com (codeload.github.com)|13.229.189.0|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [application/zip]
Saving to: ‘master.zip’

    [    <=>                                                                                                                                                                                            ] 482,045      645KB/s   in 0.7s   

2019-09-16 05:26:38 (645 KB/s) - ‘master.zip’ saved [482045]

[root@localhost soft]# unzip master.zip 
Archive:  master.zip
14edb44071b27599a5fc8c818b643eed6fe15e11
   creating: fastdfs-master/
....

二、进入fastdfs-master/docker/dockerfile_network目录,执行打包命令

[root@localhost soft]# cd fastdfs-master/docker/dockerfile_network
[root@localhost dockerfile_network]# 

打包(注意,你的宿主机内存至少要2G,不然会报错如下:)我之前只分配给宿主机1G内存,明显不够用。

如果还不行,清理一下yum缓存

# yum clean all
Loaded plugins: fastestmirror, langpacks
Cleaning repos: base docker-ce-stable extras updates
Cleaning up everything
Maybe you want: rm -rf /var/cache/yum, to also free up space taken by orphaned data from disabled or removed repos

# rm -rf /var/cache/yum

好,执行命令打包:(注意最后有个点)

[root@localhost dockerfile_network]# docker build -t local/fastdfs:latest .
Sending build context to Docker daemon   68.1kB
Step 1/13 : FROM centos
 ---> 67fa590cfc1c
Step 2/13 : ADD conf/client.conf /etc/fdfs/
 ---> Using cache
 ---> f6d4d01d7cf4
Step 3/13 : ADD conf/http.conf /etc/fdfs/
 ---> Using cache
 ---> 09b5d6e42010
Step 4/13 : ADD conf/mime.types /etc/fdfs/
 ---> Using cache
 ---> 01ba930f4e2a
Step 5/13 : ADD conf/storage.conf /etc/fdfs/
 ---> Using cache
 ---> 628d5f17543d
Step 6/13 : ADD conf/tracker.conf /etc/fdfs/
 ---> Using cache
 ---> b62b681c8ee8
Step 7/13 : ADD fastdfs.sh /home
 ---> Using cache
 ---> 6f0ffb43c5fc
Step 8/13 : ADD conf/nginx.conf /etc/fdfs/
 ---> Using cache
 ---> 6e2dded720b5
Step 9/13 : ADD conf/mod_fastdfs.conf /etc/fdfs
 ---> Using cache
 ---> 6feff4c6bb23
Step 10/13 : RUN yum install git gcc gcc-c ++ make automake autoconf libtool pcre pcre-devel zlib zlib-devel openssl-devel wget vim -y   &&    cd /usr/local/src    &&    git clone https://github.com/happyfish100/libfastcommon.git --depth 1          &&    git clone https://github.com/happyfish100/fastdfs.git --depth 1      &&    git clone https://github.com/happyfish100/fastdfs-nginx-module.git --depth 1     &&    wget http://nginx.org/download/nginx-1.15.4.tar.gz      &&    tar -zxvf nginx-1.15.4.tar.gz      &&    mkdir /home/dfs     &&    cd /usr/local/src/    &&    cd libfastcommon/     &&    ./make.sh && ./make.sh install    &&    cd ../    &&    cd fastdfs/     &&    ./make.sh && ./make.sh install    &&    cd ../    &&    cd nginx-1.15.4/    &&    ./configure --add-module=/usr/local/src/fastdfs-nginx-module/src/     &&    make && make install    &&    chmod +x /home/fastdfs.sh
 ---> Using cache
 ---> 59424d66e1a1
Step 11/13 : VOLUME /etc/fdfs
 ---> Using cache
 ---> d72d68fd5ebf
Step 12/13 : EXPOSE 22122 23000 8888 80
 ---> Using cache
 ---> f0c2d84a954e
Step 13/13 : ENTRYPOINT ["/home/fastdfs.sh"]
 ---> Using cache
 ---> fc76c652493b
Successfully built fc76c652493b
Successfully tagged local/fastdfs:latest

(额,这是我第二次打包,我第一次打包输出好多内容的,你们自行体会,你们应该能看见  ---> Using cache 利用了缓存)

 

另:网友打包把体积缩小到30M左右,需要修改Dockerfile成如下所示,打包过程不变如上所示(https://github.com/happyfish100/fastdfs/issues/327

FROM alpine:3.10

RUN set -x \
    && echo "http://mirrors.aliyun.com/alpine/latest-stable/main/" > /etc/apk/repositories \
    && echo "http://mirrors.aliyun.com/alpine/latest-stable/community/" >> /etc/apk/repositories \
    && apk update \
    && apk add --no-cache --virtual .build-deps gcc libc-dev make perl-dev openssl-dev pcre-dev zlib-dev git \
    && mkdir -p /usr/local/src \
    && cd /usr/local/src \
    && git clone https://github.com/happyfish100/libfastcommon.git --depth 1 \
    && git clone https://github.com/happyfish100/fastdfs.git --depth 1    \
    && git clone https://github.com/happyfish100/fastdfs-nginx-module.git --depth 1  \
    && wget http://nginx.org/download/nginx-1.15.4.tar.gz \
    && tar -xf nginx-1.15.4.tar.gz \
    && cd /usr/local/src/libfastcommon \
    && ./make.sh \
    && ./make.sh install \
    && cd /usr/local/src/fastdfs/ \
    && ./make.sh \
    && ./make.sh install \
    && cd /usr/local/src/nginx-1.15.4/ \
    && ./configure --add-module=/usr/local/src/fastdfs-nginx-module/src/ \
    && make && make install \
    && apk del .build-deps \
    && apk add --no-cache pcre-dev bash \
    && mkdir -p /home/dfs  \
    && mv /usr/local/src/fastdfs/docker/dockerfile_network/fastdfs.sh /home \
    && mv /usr/local/src/fastdfs/docker/dockerfile_network/conf/* /etc/fdfs \
    && chmod +x /home/fastdfs.sh \
    && rm -rf /usr/local/src*
VOLUME /home/dfs
EXPOSE 22122 23000 8888 8080
CMD ["/home/fastdfs.sh"]

测试上传

这里面有个坑。先启动镜像

docker run -d -e FASTDFS_IPADDR=[宿主机地址] -p 8888:8888 -p 22122:22122 -p 23000:23000 -p 8011:80 --name test-fast local/fastdfs

然后客户端上传,报错。com.github.tobato.fastdfs.exception.FdfsConnectException: 无法获取服务端连接资源:can't create connection to/172.17.0.1:23000

 

 为什么呢,首先我们客户端连接提供了tracker的地址,这个地址可以访问的,已经将22122端口映射到宿主机上了,而客户端的storage地址是通过tracker获取的,而这个地址则是Docker的容器地址,不能直接访问,所以连接超时。

进入容器能看到storage的地址如下:

 

你查看容器信息:

$ docker inspect 437c7bde65f8

在最后有地址信息,可见网关地址和实际地址

 

也就是说,tracker把Docker容器的网关地址当成了storage的地址

思考过程

网上有人说,利用iptables配置转发规则即可,可是我按照它的方法没有成功,那么根据转发这个思路分析一下。

目前我的环境大概是这样的

首先,Java客户端根据获取的storage地址(172.17.0.1:23000)去请求,到底能不能经过网段192.*的虚拟机,我们知道路由表的概念:(引用网友通俗的解释)

路由表是机器使用网络时要查找的一个表项,根据路由表来查找发送到特定IP的信息该发送到那个下一跳。

比如你的机子要发送一个信息到192.168.2.8,它就要查路由表到底应该怎么发,假设它查出的结果是可以直接发送,那就直接发送,否则就查出来应该发送到哪个IP,交给那个IP转发。

那么我们看一下我本机的路由表,执行: route print -4 【-6代表IPv6,不加打印全部】

 

 我在搜索一下172的

 

 没有,证明什么,凭借172*的地址,我哪也去不了,所以不会到达虚拟机,到达不了虚拟机,网上说的转发是转发什么呢?所以根本行不通吧。

我们再来看我虚拟机上的路由表

 

 没错,存在172的网段,但是,你要玩172,也要先进入虚拟机才行。而Java客户端是直接去请求172地址的,那就别想了。哪也去不了。

=====================================================================================================

以下是我查阅的资料:

关于Docker网络:https://docs.docker.com/network/

Docker网络模式:https://www.cnblogs.com/yy-cxd/p/6553624.html

iptables的介绍:http://www.zsythink.net/archives/1199

iptables简单增删查改:https://www.cnblogs.com/bethal/p/5806525.html

路由表:https://www.cnblogs.com/baiduboy/p/7278715.html

路由寻址过程:https://blog.csdn.net/u011857683/article/details/83795279

 

后记:仔细想一下,如果你分开容器部署可能也会出现同样的问题,问题就在于我们无法为storage强制配一个地址,这样的结果在Docker环境下就成了:tracker获取到的storage地址永远都是容器网关地址,而不是映射外网地址。

也有个网友这样想的,但需要修改代码:

 

 

另外我也明白了那个iptables网友的思路:他觉得是因为在请求tracker,tracker返回storage地址的时候去修改(将返回的172.17.0.1:23000修改为宿主机地址),可是我没有成功。

最后一种方法,就是使用host网络模式,这样就不存在二层网络了,妈妈再也不用担心地址错误了。

[root@localhost admin]# docker run -d -e FASTDFS_IPADDR=192.168.192.128 --name test-fast --net=host local/fastdfs-2
047250f19cad90af03ae979e8a646fff61349883f7ecdb38f72d063bd93e3f80
[root@localhost admin]# 

然后客户端上传文件

<dependency>
    <groupId>com.github.tobato</groupId>
    <artifactId>fastdfs-client</artifactId>
    <version>1.26.6</version>
</dependency>

application.properties

#连接时间
fdfs.connect-timeout=600
#读取时间
fdfs.so-timeout=2000
#缩略图
fdfs.thumb-image.width=96
fdfs.thumb-image.height=128
#tracker列表
fdfs.tracker-list=192.168.192.128:22122

# 自定义属性,图片访问地址
img.host=http://192.168.192.128:8888/

工具类

import com.alibaba.fastjson.JSONObject;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.domain.fdfs.ThumbImageConfig;
import com.github.tobato.fastdfs.domain.upload.FastFile;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.InputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

/**
 * 不会出现网上说的jmx重复注册bean的问题,是FastDFS-Client 1.26.4版本以前引入方式
 */
@Component
@Slf4j
public class UploadToFastDFS {

    @Autowired
    protected FastFileStorageClient storageClient;

    @Autowired
    private ThumbImageConfig thumbImageConfig;

    @Value("${img.host}")
    private String imgHost;

    /**
     * 上传文件并生成缩略图
     * @param inputStream
     * @param fileSize
     * @param fileExtName
     * @return
     */
    public Map<String, String> uploadFile(InputStream inputStream, Long fileSize, String fileExtName){
        Map<String, String> map = new HashMap<>();
        log.info("##上传文件...");
        FastFile fastFile = new FastFile.Builder()
                .withFile(inputStream, fileSize, fileExtName)
                .build();

        // 上传文件
        StorePath storePath = storageClient.uploadImageAndCrtThumbImage(inputStream, fileSize, fileExtName, new HashSet<>());
        log.info("上传文件结果...{}", storePath);
        // 带分组的路径
        String fullPath = storePath.getFullPath();
        log.info("带分组的路径...{}", fullPath);
        String path = storePath.getPath();
        log.info("路径...{}", path);
        // 获取缩略图路径
        String thumbImagePath = thumbImageConfig.getThumbImagePath(storePath.getPath());
        log.info("缩略图路径...{}", thumbImagePath);

        map.put("fullPath", imgHost + fullPath);
        map.put("thumbImagePath", imgHost + storePath.getGroup() + "/" + thumbImagePath);
        log.info("返回结果:{}" + JSONObject.toJSONString(map));
        // 返回结果:{}{"fullPath":"http://192.168.192.128:8888/group1/M00/00/00/wKjAgF2C7aqAcJNzAAFRSnsPpGY738.png","thumbImagePath":"http://192.168.192.128:8888/group1/M00/00/00/wKjAgF2C7aqAcJNzAAFRSnsPpGY738_96x128.png"}
        return map;
    }

}

测试类

    @Autowired
    private UploadToFastDFS uploadToFastDFS;

    @Test
    public void contextLoads() throws IOException {
        FileInputStream in = new FileInputStream("3d4cdbb229559df79d93a30e27f8d521.png");
        uploadToFastDFS.uploadFile(in, in.getChannel().size(), "png");
    }

 

 浏览器访问

http://192.168.192.128:8888/group1/M00/00/00/wKjAgF2C4zaAEFIXAAFRSnsPpGY325.png

 

posted @ 2019-09-16 19:42  露娜妹  阅读(3238)  评论(3编辑  收藏  举报