Docekr学习笔记四构建并测试web应用程序

  1. 构建Sinatra应用程序创建sinatra工作目录,编写Dockerfile文件构建一个镜像,并利用该镜像生成容器应用。重点我们将讲述如何将多个容器连接形成应用栈。
    $ md sinatra && cd sinatra
    $ vi Dockerfile
    
    FROM ubuntu
    MAINTAINER Kael Wang zb55@foxmail.com
    ENV REFRESHED_AT 2016-12-12
    RUN apt-get update
    RUN apt-get -y install ruby ruby-dev build-essential redis-tools
    RUN gem install --no-rdoc --no-ri sinatra json redis
    RUN mkdir -p /opt/webapp
    EXPOSE 4567
    CMD ["/opt/webapp/bin/webapp"]
    
    $ docker build -t kaelwang/sinatra .
    Sending build context to Docker daemon 10.24 kB
    Step 1 : FROM ubuntu
     ---> 44f18eb3c13f
    Step 2 : MAINTAINER Kael Wang zb55@foxmail.com
     ---> Using cache
     ---> 0230268896a0
    Step 3 : ENV REFRESHED_AT 2016-12-12
     ---> Using cache
     ---> 4aad3f178a57
    Step 4 : RUN apt-get update
     ---> Using cache
     ---> 254a26583566
    Step 5 : RUN apt-get -y install ruby ruby-dev build-essential redis-tools
     ---> Using cache
     ---> 3a0a3f602557
    Step 6 : RUN gem install --no-rdoc --no-ri sinatra json redis
     ---> Using cache
     ---> 933b8b6d6d84
    Step 7 : RUN mkdir -p /opt/webapp
     ---> Using cache
     ---> 710d3db42f72
    Step 8 : EXPOSE 4567
     ---> Using cache
     ---> 01c8718f0607
    Step 9 : CMD /opt/webapp/bin/webapp
     ---> Running in 2acb0e4a3bc3
     ---> d9d3d801d9e1
    Removing intermediate container 2acb0e4a3bc3
    Successfully built d9d3d801d9e1
    
    docker run -d -p 4567 --name webapp -v $PWD/webapp:/opt/webapp kaelwang/sinatra
    19a8e0112a32e93505dcf49d2852f9035d5ecbbf4a3fe960269e78a1187af755
    
    $ docker logs webapp
    [2016-07-27 06:40:04] INFO  WEBrick 1.3.1
    [2016-07-27 06:40:04] INFO  ruby 2.3.1 (2016-04-26) [x86_64-linux-gnu]
    == Sinatra (v1.4.7) has taken the stage on 4567 for development with backup from WEBrick
    [2016-07-27 06:40:04] INFO  WEBrick::HTTPServer#start: pid=1 port=4567
    
    $ docker ps -a
    CONTAINER ID        IMAGE                      COMMAND                  CREATED             STATUS                   PORTS                         NAMES
    19a8e0112a32        kaelwang/sinatra           "/opt/webapp/bin/weba"   5 seconds ago       Up 3 seconds             0.0.0.0:32770->4567/tcp       webapp
    

    目前,我们已经建立了sinatra容器应用,此应用还很基础,指示接受输入参数,并将输入转化为JSON输出。现在,我们用curl命令来测试这个应用程序。

    $ curl -i -H 'Accept:application/json' -d 'name=Foo&status=Bar' http://localhost:32770/json
    HTTP/1.1 200 OK 
    Content-Type: text/html;charset=utf-8
    Content-Length: 29
    X-Xss-Protection: 1; mode=block
    X-Content-Type-Options: nosniff
    X-Frame-Options: SAMEORIGIN
    Server: WEBrick/1.3.1 (Ruby/2.3.1/2016-04-26)
    Date: Wed, 27 Jul 2016 06:46:33 GMT
    Connection: Keep-Alive
    
    {"name":"Foo","status":"Bar"}
    

    我们可以看到,给sinatra应用程序传入了一些参数,并转化为了json散列后输出:{“name”:”Foo”,”status”:”Bar”}成功。

    我们添加一个服务,这个服务运行在另一个容器里,把当前的示例应用程序扩展为真正的应用栈。

  2. 构建Redis镜像和容器扩展sinatra应用程序,加入Redis后端数据库,并在Redis数据库中存储输入的参数。为了达到这个目的,要构建全新的镜像和容器运行redis数据库。之后,利用Docker的特性来关联两个容器。
    $ md redisdocker&&cd redisdocker
    $ vi Dockerfile
    
    FROM ubuntu
    MAINTAINER Kael Wang zb55@foxmail.com
    ENV REFRESHED_AT 2016-12-12
    RUN apt-get update
    RUN apt-get -y isntall redis-server redis-tools
    EXPOSE 6379
    ENTRYPOINT ["/usr/bin/redis-server"]
    CMD []
    
    $ docker build -t kaelwang/redis .
    Sending build context to Docker daemon 2.048 kB
    Step 1 : FROM ubuntu
     ---> 44f18eb3c13f
    Step 2 : MAINTAINER Kael Wang zb55@foxmail.com
     ---> Using cache
     ---> 0230268896a0
    Step 3 : ENV REFRESHED_AT 2016-12-12
     ---> Using cache
     ---> 4aad3f178a57
    Step 4 : RUN apt-get update
     ---> Using cache
     ---> 254a26583566
    Step 5 : RUN apt-get -y install redis-server redis-tools
     ---> Using cache
     ---> d0cf8437fb46
    Step 6 : EXPOSE 6379
     ---> Using cache
     ---> 7a8d1aa862b4
    Step 7 : ENTRYPOINT /usr/bin/redis-server
     ---> Running in c0ce2aeb9eda
     ---> dd4f375c2236
    Removing intermediate container c0ce2aeb9eda
    Step 8 : CMD 
     ---> Running in a386c0559e6c
     ---> e730c0e265d3
    Removing intermediate container a386c0559e6c
    Successfully built e730c0e265d3
    

    从这个镜像构建容器

    $ docker run -d -p 6379 --name redis kaelwang/redis
    6fdcfc399370872475d654563c24c54c3c9a1c67806a2d7eee7a2eaea8175269
    
    $ docker port redis
    6379/tcp -> 0.0.0.0:32771
    

    我们用本机redis测试一下容器里的redis服务是否工作

    $ redis-cli  -h 127.0.0.1 -p 32771
    127.0.0.1:32771> 
    
  3. Docker容器网络知识现在来更新sinatra应用程序,让其连接到redis并存储传入的参数。为此,需要能够与redis服务器对话,要做到这一点,可以有几种方法。第一种涉及Docker自己的网络栈。到目前为止,我们看到的Docker容器都是公开端口并绑定到本地网络接口的,这样可以吧容器里的服务在本地 Docker宿主机所在的外部网络上公开,除了这样方法,Docker这个特性还有种内部网络。在安装Docker时,会创建一个新的网络接口,名字是 docker0.每个Docker容器都会在这个接口上分配一个ip地址。
    $ ip a show docker0
    3: docker0: <broadcast,multicast,up,lower_up> mtu 9001 qdisc noqueue state UP group default 
        link/ether 02:42:3e:8e:ae:4d brd ff:ff:ff:ff:ff:ff
        inet 172.17.0.1/16 scope global docker0
           valid_lft forever preferred_lft forever
        inet6 fe80::42:3eff:fe8e:ae4d/64 scope link 
           valid_lft forever preferred_lft forever
    

    docker0是一个虚拟的以太网桥,用于连接容器和本地宿主机。docker0复合RFC1918的私有ip地址,范围是172.16.x.x到172.30.x.x同时Docker网络必须还要依赖防火墙和NAT规则才能允许被建立连接

    $ iptables -t nat -L -n
    Chain PREROUTING (policy ACCEPT)
    target     prot opt source               destination         
    DOCKER     all  --  0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL
    
    Chain INPUT (policy ACCEPT)
    target     prot opt source               destination         
    
    Chain OUTPUT (policy ACCEPT)
    target     prot opt source               destination         
    DOCKER     all  --  0.0.0.0/0           !127.0.0.0/8          ADDRTYPE match dst-type LOCAL
    
    Chain POSTROUTING (policy ACCEPT)
    target     prot opt source               destination         
    MASQUERADE  all  --  172.17.0.0/16        0.0.0.0/0           
    MASQUERADE  tcp  --  172.17.0.3           172.17.0.3           tcp dpt:80
    MASQUERADE  tcp  --  172.17.0.4           172.17.0.4           tcp dpt:4567
    MASQUERADE  tcp  --  172.17.0.5           172.17.0.5           tcp dpt:6379
    
    Chain DOCKER (2 references)
    target     prot opt source               destination         
    DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:80 to:172.17.0.3:80
    DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:32770 to:172.17.0.4:4567
    DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:32771 to:172.17.0.5:6379
    

    容器默认是无法访问的,从宿主网络与容器通信时,必须明确指定打开的端口,下面我们以DNAT即目标NAT这个规则为例,这个规则吧容器里的访问路由到Docker宿主机的32771端口。

  4. 通过Docker内网连接Redis
    $ docker inspect redis
    	.
    	.
    	.
        "NetworkSettings": {
        "Bridge": "",
        "SandboxID": "b4bb7703aa7d658f8309abbfcdf7fe575ac5faa3546805e33dc44be86e3932cb",
        "HairpinMode": false,
        "LinkLocalIPv6Address": "",
        "LinkLocalIPv6PrefixLen": 0,
        "Ports": {
            "6379/tcp": [
                {
                    "HostIp": "0.0.0.0",
                    "HostPort": "32771"
                }
            ]
        },
        "SandboxKey": "/var/run/docker/netns/b4bb7703aa7d",
        "SecondaryIPAddresses": null,
        "SecondaryIPv6Addresses": null,
        "EndpointID": "8e96a4e055c46a34331f3ae3b3c455ecdcddb6a16b2650fe53cdb638127e5255",
        "Gateway": "172.17.0.1",
        "GlobalIPv6Address": "",
        "GlobalIPv6PrefixLen": 0,
        "IPAddress": "172.17.0.5",
        "IPPrefixLen": 16,
        "IPv6Gateway": "",
        "MacAddress": "02:42:ac:11:00:05",
        "Networks": {
            "bridge": {
                "EndpointID": "8e96a4e055c46a34331f3ae3b3c455ecdcddb6a16b2650fe53cdb638127e5255",
                "Gateway": "172.17.0.1",
                "IPAddress": "172.17.0.5",
                "IPPrefixLen": 16,
                "IPv6Gateway": "",
                "GlobalIPv6Address": "",
                "GlobalIPv6PrefixLen": 0,
                "MacAddress": "02:42:ac:11:00:05"
            }
        }
    	.
    	.
    	.
    

    docker inspect命令展示Docker容器的细节,这里只显示网络信息。容器的ip地址为172.17.0.5,并使用网关172.17.0.1即 docker0。也可以看到容器6379端口被映射到本地宿主机32771端口。只是,因为运行在本地Docker宿主机上,所以不是一定要用映射的端 口,也可以直接使用Docker0分配的内网地址

    $ redis-cli  -h 172.17.0.5
    172.17.0.5:6379> 
    

    但是,通过这种方法连接两个容器,有两个大问题,第一,要在应用内对redis容器的ip地址做硬编程,第二,如果重启或容器意外中断后恢复,Docker会改变容器的ip地址。

  5. 引用容器名字让两个容器相连首先删掉原来我们构建的Sinatra和redis容器,然后重新构建一个新的Sinatra和redis容器
    $ docker stop redis sinatra
    $ docker rm redis sinatra
    

    实现连接

    $ docker run -d --name redis kaelwang/redis
    a843b4e5adaa3630a08ebdbe8828a6028fbf6331ba537f082f4484dff8a6b27b
    
    $ docker run -p 4567 --name webapp --link redis:db -t -i -v $PWD/webapp:/opt/webapp kaelwang/sinatra /bin/bash
    root@d205ff072682:/# cat /etc/hosts
    172.17.0.4      d205ff072682
    127.0.0.1       localhost
    ::1     localhost ip6-localhost ip6-loopback
    fe00::0 ip6-localnet
    ff00::0 ip6-mcastprefix
    ff02::1 ip6-allnodes
    ff02::2 ip6-allrouters
    172.17.0.5      db a843b4e5adaa redis
    
    root@d205ff072682:/# env
    HOSTNAME=d205ff072682
    DB_NAME=/webapp/db
    DB_PORT_6379_TCP_PORT=6379
    TERM=xterm
    DB_PORT=tcp://172.17.0.5:6379
    DB_PORT_6379_TCP=tcp://172.17.0.5:6379
    LS_COLORS=rs=0:di=01;34:ln=01;...(此处信息较多省略)
    DB_ENV_REFRESHED_AT=2016-12-12
    PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    REFRESHED_AT=2016-12-12
    PWD=/
    DB_PORT_6379_TCP_ADDR=172.17.0.5
    DB_PORT_6379_TCP_PROTO=tcp
    SHLVL=1
    HOME=/root
    _=/usr/bin/env
    root@d205ff072682:/# 
    

    –link标志创建了两个容器间的父子相连,这个标志需要两个参数,一个是要连接的容器名字,另一个是连接后容器的别名。此处别名是db,别名让 我们可以访问公开的信息,而无需关注底层容器的名字,连接让父容器有能力访问子容器,并且把子容器的一些连接细节分享给父容器。这些细节有助于配置应用程 序并使用这个连接。

    连接也能得到一些安全上的额好处。启动redis容器时,并没有使用-p标志公开redis的端口。通过父容器直接访问任意子容器的公开端口。且只 有使用的–link标志连接到这个容器的容器才能连接到这个端口,容器的端口不需要对本地宿主机公开,现在我们已经拥有了一个非常安全的模型,在这个模 型里,容器话的应用程序限制了可被攻击的界面,减少了公开暴露的网络。也可以吧多个容器连接到一起,比如一个redis示例服务于多个web应用服务器。 出于一些原因,我们可以在启动Docker守护进程时加上–icc=false标志,关闭所有没有连接的容器间的通讯,这样强制Docker只允许有连 接的容器之间相互通信。

    我们通过env查看环境变量发现有一些以别名DB开头的,Docker在连接webapp和redis容器时,自动创建了这些以DB开头的环境变量。 这些自动创建的环境变量包含以下信息。

    • 子容器的名字
    • 容器里运行的服务所使用的协议,ip和端口
    • 容器里运行的不同的服务所指定的协议,ip和端口
    • 容器里由Docker设置的环境变量的值。
  6. 使用容器连接来通信
    1. 使用环境变量里的一些连接信息。
    2. 使用DNS和/etc/hosts信息。

    应用程序会在本地查找名叫db的主机,找到/etc/hosts文件里的项解析到正确的ip地址,这也解决了硬编码IP地址的问题,因为hosts文件会随着你的Docker启动时自动更新相应信息。

    这个web应用程序栈由以下几部分组成

    • 一个运行Sinatra和web服务器容器
    • 一个Redis数据库容器
    • 两个容器间的一个安全连接

    这样就可以在本地环境构建,复制,迭代开发用于生产的应用程序,甚至很多复杂的多层应用程序。

分类: Docker

112 条评论

https://pzfs.eu · 2026-09-02 12:51

References:

Australian on line pokies https://pzfs.eu

福利视频 · 2026-09-08 17:44

Excellent website. A llot oof helppful information here. I amm sendcing it too
a few buddies anns additionzlly sharing iin delicious. And obviously, thanks in yolur effort!
xnxx

dmgameloginbet · 2026-09-13 12:40

Logged into dmgameloginbet last night and had a blast! The games are actually pretty fun and the site’s pretty user-friendly. Good way to kill some time. Log in here: dmgameloginbet

pbase.com · 2026-09-22 03:27

References:

Casino mit sofort erfahrungen pbase.com

Neue Online Casinos mit Sofort · 2026-09-22 06:11

References:

Sofort Casino Vergleich Neue Online Casinos mit Sofort

https://pad.funkwhale.audio/ · 2026-09-22 21:19

References:

Casino mit sofortiger auszahlung https://pad.funkwhale.audio/

https://comsenz-service.com/?182553 · 2026-09-23 02:25

References:

Online casino schnelle auszahlung sofort
https://comsenz-service.com/?182553

http://bbs.wuhudj.com · 2026-09-23 03:45

References:

Klarna sofortüberweisung casino http://bbs.wuhudj.com

casino ohne limit sofortüberweisung · 2026-09-23 03:46

References:

Online casino mit sofortüberweisung einzahlung http://www.lezcc.com/?618842

http://www.jzq5.cn/ · 2026-09-23 05:23

References:

Instant withdrawal payid pokies http://www.jzq5.cn/space-uid-458864.html

http://www.qilurexian.net/?241572 · 2026-09-23 06:53

References:

Online casino sofortüberweisung test http://www.qilurexian.net/?241572

sofort online casino · 2026-09-23 15:48

References:

Legale sofort casinos deutschland http://bbs.51pinzhi.cn/home.php?mod=space&uid=8376266

online pokies payid australia · 2026-09-25 23:10

References:

How to play pokies with payid https://hedgedoc.envs.net/ZPCDvPMlSf211s3EH1-nyA

best payid pokies sites · 2026-09-26 03:19

References:

Play pokies with payid https://md.interhacker.space/eQS66o2OSyGnoJhbcNadbQ

pbase.com · 2026-09-28 23:14

References:

How to play pokies with payid https://pbase.com/targetvinyl41/

md.coredump.ch · 2026-09-29 15:07

References:

Anonymous payid pokies https://md.coredump.ch/oGq7urokSxiqqC95vaBQMg

payid online pokies · 2026-09-29 15:39

References:

Payid pokies free spins https://docs.monadical.com/m1Ai9e_oSmuRHxIeJ7ktcw

bandori.party · 2026-09-29 21:48

References:

Payid pokies no deposit bonus https://bandori.party/user/1770827/lierdew87/

online pokies that accept payid · 2026-09-30 06:38

References:

Fast payout payid pokies https://www.akaguide.com/user/greasecat69

bbs.ybk001.com · 2026-09-30 18:28

References:

No deposit payid pokies australia https://bbs.ybk001.com/home.php?mod=space&uid=611393

https://iskustva.net · 2026-09-30 23:26

References:

Pokies with payid deposit https://iskustva.net/user/radarspace3

forum.issabel.org · 2026-10-01 03:22

References:

Pokies sites that take payid https://forum.issabel.org/u/cubandream64

payid deposit online pokies · 2026-10-02 00:58

References:

No verification payid pokies australia http://bbs.wuhudj.com/space-uid-1769246.html

top neosurf casinos australia · 2026-10-04 00:53

References:

Neosurf online pokies australia real money http://qiaoxiaojun.vip/home.php?mod=space&uid=2668510

http://mashspec.ru/ · 2026-10-04 05:02

References:

Neosurf casino tips australia http://mashspec.ru/user/fanwarm4/

https://codimd.syssec.org/ · 2026-10-04 05:51

References:

$1 minimum deposit casino neosurf australia https://codimd.syssec.org/8r0EoRtjRWezytT0bg1O5Q

http://www.lezcc.com · 2026-10-04 07:53

References:

Neosurf casino welcome bonus http://www.lezcc.com/?610361

https://undrtone.com/ · 2026-10-04 08:12

References:

Trusted payid pokies australia https://undrtone.com/taiwandesign67

anonymous payid pokies · 2026-10-04 08:42

References:

Bonus pokies payid http://bbs.wuhudj.com/space-uid-1770076.html

neosurf no deposit bonus australia · 2026-10-04 14:31

References:

Neosurf casino sites accepting australian players https://xn—-7sbarohhk4a0dxb3c.xn--p1ai/user/whalesquid8/

https://hedgedoc.uni-ak.ac.at/U74eTZdXQs6bp59E_Ov3YA · 2026-10-05 03:01

References:

How to deposit with neosurf at online casinos https://hedgedoc.uni-ak.ac.at/U74eTZdXQs6bp59E_Ov3YA

md.coredump.ch · 2026-10-06 00:38

References:

Neosurf voucher online casino australia https://md.coredump.ch/qJfbdX1ERvWg-N2K9LTOJQ

neosurf reload casino australia · 2026-10-06 04:57

References:

Neosurf casino fees australia http://www.sg588.tw/home.php?mod=space&uid=1296880

http://asresin.cn · 2026-10-06 05:08

References:

Neosurf prepaid voucher casino australia http://asresin.cn/home.php?mod=space&uid=1259908

neosurf casino australia review · 2026-10-06 05:29

References:

$5 minimum deposit casino neosurf australia http://www.seafishzone.com/home.php?mod=space&uid=3270125

https://text.fraction.jp · 2026-10-06 05:42

References:

Best neosurf casinos australia https://text.fraction.jp/jBh0nnWqT0acSH4J9roHLA

http://forum.djwx.com/ · 2026-10-06 05:49

References:

Play pokies with neosurf http://forum.djwx.com/home.php?mod=space&uid=57857

http://t.044300.net/ · 2026-10-06 11:19

References:

Neosurf no verification casino australia http://t.044300.net/home.php?mod=space&uid=3142654

www.vamudhumeni.org · 2026-10-06 13:19

References:

How to use neosurf at casino australia https://www.vamudhumeni.org/forums/users/maracaday33/

licensed wire transfer casino Australia · 2026-10-17 02:56

References:

Wire transfer real money pokies australia http://downarchive.org/user/timechef3/

madk-auto.ru · 2026-10-17 23:11

References:

Legit bank transfer casino australia http://madk-auto.ru/user/avenuefarmer49/

trusted bpay pokie sites · 2026-10-18 07:31

References:

BPay vs credit card casino deposit https://pad.cttue.de/SmwUrG8AQ5mchmgSBM9QdQ

http://ambimomes.online.fr/ · 2026-10-18 19:09

References:

Fastest withdrawal MiFinity casino Australia http://ambimomes.online.fr/forums/member.php?action=profile&uid=26551

neosurf casino welcome bonus · 2026-10-19 09:26

References:

Neosurf free spins no deposit australia https://topsitenet.com/profile/pastorpea60/2655953/

fast payout wire transfer casino australia · 2026-10-19 22:22

References:

Live bank transfer casino australia http://xhdyz.cn/home.php?mod=space&uid=1234915

docs.monadical.com · 2026-10-20 23:21

References:

Safe wire transfer casino Australia https://docs.monadical.com/EpFlaqXLRluT_3HwQ7PacQ

ele777plataform · 2026-10-21 06:28

I have been playing for years and this platform reminded me why I fell in love with the game in the first place. The interface is clean, the tournaments are thrilling, and cashouts never get stuck in some weird review cycle. It truly puts the player first every single time. Grab your phone and join the fun today. ele777plataform

top payid pokies australia · 2026-10-21 18:58

References:

5 minimum deposit pokies payid https://dok.kompot.si/G3jxTlvWRWO6FxAbKVlm8Q

https://prpack.ru/user/joinpet90/ · 2026-10-21 22:51

References:

MiFinity casino welcome bonus https://prpack.ru/user/joinpet90/

20 dollar neosurf deposit casino · 2026-10-22 08:25

References:

$1 minimum deposit casino neosurf australia http://maskarad.bomba-piter.ru/user/bubblefiber7/

mashspec.ru · 2026-10-23 16:21

References:

Australian bank wire casinos http://mashspec.ru/user/creekdollar75/

https://undrtone.com/combplier86 · 2026-10-23 17:40

References:

Osko pokies real play https://undrtone.com/combplier86

https://cq.x7cq.vip · 2026-10-23 22:47

References:

Wire transfer casino banking options Australia https://cq.x7cq.vip/home.php?mod=space&uid=9736159

MiFinity pokies Australia · 2026-10-27 11:58

References:

MiFinity casino tablet Australia https://www.sqlservercentral.com/forums/user/shrimprun48/edit

https://winnipegasians.com · 2026-10-28 02:57

References:

High roller wire transfer casino australia https://winnipegasians.com/home.php?mod=space&uid=311317

berrypen1.werite.net · 2026-10-28 16:57

References:

Fast withdrawal casinos Osko https://berrypen1.werite.net/youtube-apps-on-google-play

fairpari · 2026-11-09 01:42

[7389]fairpari লগইন এবং অ্যাপ ডাউনলোড | বিকাশ পেমেন্ট ও স্লটস গেম,fairpari-তে সহজেই login করার নিয়ম জানুন এবং app download link থেকে অ্যাপটি নিন। বিকাশ দিয়ে অনলাইন casino সাইটে সেরা slots গেম খেলুন। visit: fairpari

发表回复

Avatar placeholder

您的邮箱地址不会被公开。 必填项已用 * 标注