#
http://www.runoob.com/mongodb/mongodb-aggregate.html
MongoDB中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果。有点类似sql语句中的 count(*)。
aggregate() 方法
MongoDB中聚合的方法使用aggregate()。
语法
aggregate() 方法的基本语法格式如下所示:
>db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)
实例
集合中的数据如下:
{ _id: ObjectId(7df78ad8902c) title: 'MongoDB Overview', description: 'MongoDB is no sql database', by_user: 'w3cschool.cc', url: 'http://www.w3cschool.cc', tags: ['mongodb', 'database', 'NoSQL'], likes: 100 }, { _id: ObjectId(7df78ad8902d) title: 'NoSQL Overview', description: 'No sql database is very fast', by_user: 'w3cschool.cc', url: 'http://www.w3cschool.cc', tags: ['mongodb', 'database', 'NoSQL'], likes: 10 }, { _id: ObjectId(7df78ad8902e) title: 'Neo4j Overview', description: 'Neo4j is no sql database', by_user: 'Neo4j', url: 'http://www.neo4j.com', tags: ['neo4j', 'database', 'NoSQL'], likes: 750 },
现在我们通过以上集合计算每个作者所写的文章数,使用aggregate()计算结果如下:
> db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : 1}}}]) { "result" : [ { "_id" : "w3cschool.cc", "num_tutorial" : 2 }, { "_id" : "Neo4j", "num_tutorial" : 1 } ], "ok" : 1 } >
以上实例类似sql语句: select by_user, count(*) from mycol group by by_user
在上面的例子中,我们通过字段by_user字段对数据进行分组,并计算by_user字段相同值的总和。
下表展示了一些聚合的表达式:
表达式 | 描述 | 实例 |
---|
$sum | 计算总和。 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : "$likes"}}}]) |
$avg | 计算平均值 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$avg : "$likes"}}}]) |
$min | 获取集合中所有文档对应值得最小值。 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$min : "$likes"}}}]) |
$max | 获取集合中所有文档对应值得最大值。 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$max : "$likes"}}}]) |
$push | 在结果文档中插入值到一个数组中。 | db.mycol.aggregate([{$group : {_id : "$by_user", url : {$push: "$url"}}}]) |
$addToSet | 在结果文档中插入值到一个数组中,但不创建副本。 | db.mycol.aggregate([{$group : {_id : "$by_user", url : {$addToSet : "$url"}}}]) |
$first | 根据资源文档的排序获取第一个文档数据。 | db.mycol.aggregate([{$group : {_id : "$by_user", first_url : {$first : "$url"}}}]) |
$last | 根据资源文档的排序获取最后一个文档数据 | db.mycol.aggregate([{$group : {_id : "$by_user", last_url : {$last : "$url"}}}]) |
管道的概念
管道在Unix和Linux中一般用于将当前命令的输出结果作为下一个命令的参数。
MongoDB的聚合管道将MongoDB文档在一个管道处理完毕后将结果传递给下一个管道处理。管道操作是可以重复的。
表达式:处理输入文档并输出。表达式是无状态的,只能用于计算当前聚合管道的文档,不能处理其它的文档。
这里我们介绍一下聚合框架中常用的几个操作:
- $project:修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。
- $match:用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作。
- $limit:用来限制MongoDB聚合管道返回的文档数。
- $skip:在聚合管道中跳过指定数量的文档,并返回余下的文档。
- $unwind:将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。
- $group:将集合中的文档分组,可用于统计结果。
- $sort:将输入文档排序后输出。
- $geoNear:输出接近某一地理位置的有序文档。
管道操作符实例
1、$project实例
db.article.aggregate( { $project : { title : 1 , author : 1 , }} );
这样的话结果中就只还有_id,tilte和author三个字段了,默认情况下_id字段是被包含的,如果要想不包含_id话可以这样:
db.article.aggregate( { $project : { _id : 0 , title : 1 , author : 1 }});
2.$match实例
db.articles.aggregate( [ { $match : { score : { $gt : 70, $lte : 90 } } }, { $group: { _id: null, count: { $sum: 1 } } } ] );
$match用于获取分数大于70小于或等于90记录,然后将符合条件的记录送到下一阶段$group管道操作符进行处理。
3.$skip实例
db.article.aggregate( { $skip : 5 });
经过$skip管道操作符处理后,前五个文档被"过滤"掉。
摘要: 在这篇文章中,我将告诉大家我对hashCode和equals方法的理解。我将讨论他们的默认实现,以及如何正确的重写他们。我也将使用Apache Commons提供的工具包做一个实现。 目录:hashCode()和equals()的用法重写默认实现使用Apache Commons Lang包重写hashCode()和equals()需要注意记住的事情当使用ORM的时候特别要注意的hashC...
阅读全文
双清教程:
- 手机关机,按住音量上+HOME+电源键
- 选择 wipe date/factory reset
- 选择 yes dalete all user data
- 选择 wipe cache partition
- 选择 yes wipe cache
如何医治牙龈出血啊。。。谢谢啊,狂急!!!!
悬赏分:0 - 解决时间:2005-11-22 12:37
提问者: 小哈纳斯 - 魔法学徒 一级
http://www.234.com.tw/perio/topicList.cfm?kid=61
最佳答案
这里是我以前答复两个患者的资料,对你有作用:
一 关于青年人牙龈出血
⑴ 我想你是牙龈出血。若是其它原因出血,你肯定早住医院而不会在这里轻松发贴了。
⑵ 这个臭味是来自血的腐败。既然牙龈会出血,也表明你有牙周的问题,这些渗血部位的牙垢及食物残渣也会发出难闻的气味。
⑶ 治疗一般应到专门的口腔门诊。看来你是第一次涉及口腔的保健,治疗的流程应该是这样的:
先消除炎症:常规是口服利菌沙,灭滴灵,维生素C,维生素K。治疗约1周后,牙龈炎症消除,就应着手解决根本问题了。
再清除牙垢:这是引起牙周炎的原因。牙垢很硬,堆积在牙龈周围,不断地刺激和损伤着牙龈,使成创面出血。而出血又可进一步形成牙垢,如此成恶性循环。
⑷ 在我们三甲医院,这个费用偏高些,约100元。它包括消炎和约两次的除垢(洗牙)。在县市级的医院应该便宜些。
⑸ 消炎7天加除垢2天。若同时治疗龋齿,还加2天。
⑹ 当然,你也可只做消炎一步,除垢待以后有时间再做。如此,你到大的药房去,买前3种药自己服。买3-5天的量。约花20元。
⑹ 这3-5天内,你要睡眠良好,尽量避免感冒发热,那会引起血管通透性趋增,使出血严重一些,不利于治疗消炎。
⑺ 平时多食富含维生素C的水果蔬菜很重要!!!
好,暂就说这么多。对顽固性的牙龈出血(例如出了多年血),或是这样治疗仍不见效,请再设问,我们来为你确定新的治疗方案。
二 关于老是治不好的牙龈出血(先用一法!!!!)
楼上解释的对。但我要教你最重要的东西,就是怎样解决这个问题。当然,解决之后,你要补我的专家号,呵呵。(我有个熟人有40年牙龈出血的经历,可是它近年突然好了。你想知道原因吗?我给了他一个新招。)
⑴ 连服维生素C7天,每天100-300mg。(这个量不算多,意义你明白。)
⑵ 这7天内保持好睡眠,目的是调节好人的生理状态,使不容易感冒什么的,避免因发烧造成的微血管通透性能趋增,使容易出血。
⑶ 本条最重要:去药房买“阿奇霉素分散片”,买大厂出的,我建议买天津药业悦来牌的。每盒6片×0.25g,请单次口服4片,并详细阅读一下说明书。记住:只吃一次即可。若有严重的不良反应(极少有!!),带着这个药的说明书去看门诊,医生会处置。如果没有不良反应,可在48小时后把另2片吃了,仅此而已。
该药是目前极有名的药,4年前从国外进来现已完全本土化,真的是国外科学家对人类的大贡献!也不算贵,约20-30元1盒6片。主要用途是对付非淋菌性性病。
它是广谱抗菌药,更是☆靶向制剂☆。你明白这个吗?我说个白话以便你能听懂:这个药可跟随人的巨嗜细胞走。而巨嗜细胞又跟着炎症走,所以疗效显著。
⑷ 一般的牙科医生,都会建议你用利君沙和灭滴灵,外加维生素C和K。但我想你是老牙龈出血,这种药用过多次,不会太奏效,阿奇霉素毒副作用比上述两种都小,更重要的是你没用过,致病菌没有抗药性。
⑸ 炎症消除、出血停止之后,建议你去做一次牙垢清除。多年的出血肯定会导致牙根周围有比较多的牙垢,这些牙垢年复一年刺激着周围的牙龈,不但是细菌的温床,也使牙龈面持续受到创伤,牙龈出血还会卷土重来。
⑹ 此次牙龈炎症消除之后,口腔气味也会比以前好转,但牙根的一部分将暴露的比以前利害(以前被肿胀的牙龈包裹),产生龋齿的可能性将增加。因此要注意好口腔清洁。
回答者: ccd2093 - 举人 四级 11-14 08:51
提问者对于答案的评价:
非常感谢~~
如果用RSA加密数据的话,会有数据长度的要求,否则会抛异常:
javax.crypto.IllegalBlockSizeException: Data must not be longer than 256 bytes
推荐的做法:
- 随机生成一个密钥,用作对称密钥UUID
- 用此对称密钥,用对称加密法AES加密数据
- 用RSA的公钥加密此对称密钥
- 发送加密后的对称密钥和加密数据
- 用RSA私钥解密加密后的对称密钥
- 用解密密后的对称密钥,解密数据
- 完成
AESSecurityUtil.java
import java.security.Key;
import java.util.UUID;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
public class AESSecurityUtil {
// 加密算法
/** 指定加密算法为RSA */
private static final String ALGORITHM = "AES";
// 加密密钥
// private static final byte[] keyValue = new byte[] { 'T', 'h', 'e',
// 'B','e', 's', 't', 'S', 'e', 'c', 'r', 'e', 't', 'K', 'e', 'y' };
// 16位的加密密钥
// private byte[] keyValue;
/**
* 用来进行加密的操作
*
* @param Data
* @return
* @throws Exception
*/
public static String encrypt(String keyString, String data)
throws Exception {
Key key = generateKey(keyString);
Cipher c = Cipher.getInstance(ALGORITHM);
c.init(Cipher.ENCRYPT_MODE, key);
byte[] encVal = c.doFinal(data.getBytes());
String encryptedValue = new BASE64Encoder().encode(encVal);
return encryptedValue;
}
/**
* 用来进行解密的操作
*
* @param encryptedData
* @return
* @throws Exception
*/
public static String decrypt(String keyString, String encryptedData) throws Exception {
Key key = generateKey(keyString);
Cipher c = Cipher.getInstance(ALGORITHM);
c.init(Cipher.DECRYPT_MODE, key);
byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedData);
byte[] decValue = c.doFinal(decordedValue);
String decryptedValue = new String(decValue);
return decryptedValue;
}
public static String generateKeyString()
{
//必须长度为16
return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 16);
}
/**
* 根据密钥和算法生成Key
*
* @return
* @throws Exception
*/
private static Key generateKey(String keyString) throws Exception {
Key key = new SecretKeySpec(keyString.getBytes(), ALGORITHM);
return key;
}
public static void main(String [] args) throws Exception
{
String keyString = generateKeyString();
// String keyString = "1234567890123456";
System.out.println("密钥:" + keyString);
String source = "恭喜发财!";// 要加密的字符串
System.out.println("准备用密钥加密的字符串为:" + source);
String cryptograph = encrypt(keyString, source);// 生成的密文
System.out.print("用密钥加密后的结果为:" + cryptograph);
System.out.println();
String target = decrypt(keyString, cryptograph);// 解密密文
System.out.println("用密钥解密后的字符串为:" + target);
System.out.println();
}
}
CryptoUtil.java
import com.tcl.project7.boss.common.crypto.CryptoData;
import com.tcl.project7.boss.common.util.JsonManager;
import com.tcl.project7.boss.common.util.file.FileUtil;
import com.tcl.project7.boss.gameapplication.yearendactivities.bigwheelgame.player.valueobject.BigWheelGameRequest;
public class CryptoUtil {
public static CryptoData encrypt(String data) throws Exception
{
//1、产生AES密钥
String keyString = AESSecurityUtil.generateKeyString();
//2、用AES法加密数据
String cryptograph = AESSecurityUtil.encrypt(keyString, data);
//3、用RSA加密AES密钥
String finalKey = RSASecurityUtil.encrypt(keyString);
// System.out.print("用RSA加密AES密钥为:" + finalKey);
// System.out.print("加密数据:" + cryptograph);
CryptoData cryptoData = new CryptoData();
cryptoData.setKey(finalKey);
cryptoData.setContent(cryptograph);
//4、返回数据
return cryptoData;
}
public static String decrypt(String keyString, String data) throws Exception
{
//1、解密密钥
String decryptKeyString = RSASecurityUtil.decrypt(keyString);
//2、解密内容
String decryptData = AESSecurityUtil.decrypt(decryptKeyString, data);
//3、返回
return decryptData;
}
public static void main(String [] args) throws Exception
{
String aFilePath = "DATA/TESTING-FILE/TOCRYPTO/tocrypto.txt";
String source = FileUtil.getContents(aFilePath);
CryptoData cryptoData = encrypt(source);
System.out.print(cryptoData);
String target = decrypt(cryptoData.getKey(), cryptoData.getContent());
System.out.print(target);
BigWheelGameRequest bigWheelGameRequest = JsonManager.getBean(target, BigWheelGameRequest.class);
System.out.print(bigWheelGameRequest);
}
}
CryptoData.java
import java.io.Serializable;
public class CryptoData implements Serializable{
private static final long serialVersionUID = -4774469372648172844L;
private String key;
private String content;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String toString() {
return "CryptoData [key=" + key + ", content=" + content + "]";
}
}
import java.io.IOException;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ColumnControllerTest {
private Logger logger = LoggerFactory.getLogger(ColumnControllerTest.class);
@Test
public void testTest()
{
ObjectMapper mapper = new ObjectMapper();
/*AnnotationIntrospector introspector = new JaxbAnnotationIntrospector();
// make deserializer use JAXB annotations (only)
mapper.getDeserializationConfig().setAnnotationIntrospector(introspector);
// make serializer use JAXB annotations (only)
mapper.getSerializationConfig().setAnnotationIntrospector(introspector);*/
mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
String userStr = "{\"username\":\"paul\",\"email\":\"paul@paul.com\"}";
try {
TypeReference<TestUser> temp = new TypeReference<TestUser>(){};
TestUser testUser = mapper.readValue(userStr, temp);
System.out.println(testUser.toString());
String result = mapper.writeValueAsString(testUser);
System.out.println(result);
} catch (JsonParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JsonMappingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
摘要: ice-dubbo-thrift-grpc性能测试对比,本次测试过程中还发现了一个支付宝的秘密,附件文档中会详细说明。测试说明 本测试只是个人为了对rpc进行技术选型,测试可能不够严谨,对某些rpc的参数可能也不是最优,如果你知道更优的参数配置或者改进意见等,欢迎反馈给我magicdoom@gmail.com。另外代码有些地方只是为了测试方便,不作为平时编程的范例。所有测...
阅读全文
简介
Tengine是由淘宝网发起的Web服务器项目。它在
Nginx的基础上,针对大访问量网站
的需求,添加了很多高级功能和特性。Tengine的性能和稳定性已经在大型的网站如
淘宝网,
天猫商城等得到了很好的检验。它的最终目标是打造一个高效、稳定、安全、
易用的Web平台。
从2011年12月开始,Tengine成为一个开源项目,Tengine团队在积极地开发和维护
着它。Tengine团队的核心成员来自于
淘宝、
搜狗等互联网企业。Tengine是社区合作
的成果,我们欢迎大家
参与其中,贡献自己的力量。
Spring起初只专注ioc和aop,现在已发展成一个庞大体系。比如security、mvc等。
如此一来,不同模块或者与外部进行集成时,依赖处理就需要各自对应版本号。
比如,较新spring与较老的quartz,它们集成就会遇到问题,给搭建和升级带来不便。
因此Spring IO Platform应运而生,只要项目中引入了它,外部集成时依赖关系无需版本号
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
Spring IO Platform只是一个pom文件,记录了spring与其他开源项目对应的版本。
省去了版本号,也就省去了处理依赖时的问题,因为Spring IO Platform中有最优的版本。
看到这标题你可能会想,网上不是已经有很多Docker的入门介绍了么?同一个主题被讲过很多次,还有没有必要必要再讲?可是,我体内这混杂的的高傲与固执虽然让人厌恶,但却让我广受大家的欢迎,这也让我觉得我应该来一发(篇),哈哈。
举一个我遇到的场景,ELK三剑客,即Elasticsearch、Logstash和Kibana。我可以选择把它们直接安装在我的MacBook上,这是我主力开发机,但是在上面已经装好一个Elasticsearch了。我不想破坏现在已有的环境。要解决这个问题,用2015年时下最热门的解决方案就是Docker了。如果过去一年关于Docker的各种热闹你都错过了,那么请继续往下看。
Docker做的事情就是将的软件隔离起来,让它们即使出了问题也不会互相影响。这并不是什么横空出世的新思想。你很可能会说内核控制的进程不就这样玩么?每一个进程都有自己的内存空间,并且在一个进程自身看来,内存空间与所处在的计算机的内存空间是一样的。然而内核欺骗了进程,在背后将内存地址重新映射到了真实的内存空间中。想想今天高速运转处理器,任何地方见到的系统都能同时运行多个进程。今天的文明社会比人类历史任何一个时间点制造的谎言数量级都要很多的量级。
扯远了,Docker将进程的隔离模型的进行了扩展,让隔离性变得更强。Docker是在Linux内核的基础上打造的一系列工具。整个文件系统被抽象了,网络被虚拟化了,其它进程被隐藏了,并且从理论上,不可能逃脱容器去对在一个机器上的其他进程搞破坏。实际中,每个人对于怎么才能逃脱容器,至少去收集一点运行容器的机器的相关信息,持开放的态度。跟虚拟机比较起来,容器的隔离性还是较弱。
上面箭头:提升单机性能;下面箭头:提升隔离性
但换个角度看,进程比容器性能更好,容器性能比虚拟机性能更佳。原因很简单,隔离性更高,在每一个上下文中就需要运行更多的东西,从而拖慢速度。选择一个隔离性的过程,实际就是决定你对要运行进程的信任有多少的过程 - 它会不会去干扰其他的进程?如运行的进程都是自己的亲儿子,那你对他们会有一个很高的信任度,对他们用最少的隔离,运行在一个进程中就行了。如果是SAP,那么你很可能需要尽可能高的隔离性:将电脑装在封存在箱子里,绑在火箭上发射到月球。
Docker另一个很好的特性是,容器可以作为一个整体交付。他们不会像虚拟机那么臃肿。这大大的提高了部署的简易度。在这个微服务流行的世界里,你可以很容易将你的服务捆在一起,用镜像来发布。你甚至可以将build的结果指定成一个Docker镜像。
Docker将会怎样改变软件开发和部署的过程仍然有待观察。尽管我觉得Docker是一种带有破坏性的技术,但影响还在几年之后才会到来。虽然我会认为Docker会让很多系统管理员丢掉工作,但是实际上Docker却会改变他们的工作。每个人现在都需要一点变革,赶上时代的脚步。
又扯远了,说说OSX上的Docker。
细心的你可能注意到,我之前说Docker是运行在Linux内核之上的。然而OSX没有Linux内核,那怎么运行Docker呢。为了解决这个问题,我们需要用虚拟机来运行Docker。我们可以用一个叫boot2docker的工具来做这件事情,但是最近被docker-machine取代了。
我的机上有一个比较老的Docker,但是我觉得想试试Docker Compose,因为我运行着很多的服务。Docker Compose能让很多的容器协作起来运行一个整体的环境。为了遵循保证隔离服务的宗旨,每一个服务都运行在单独的容器中。因而,一个典型的web应用中,可以把web服务器运行在一个容器里面,数据库运行在另外一个容器里面,然后这些容器可以放在同一个机器上。
我从Docker官网上下载了安装包,并且跟着安装指南
http://docs.docker.com/mac/step_one/安装。装好Docker后,我让docker-machine在Virtual Box上创建了新的虚拟机。
一起看起来很顺利,然后启动随处可见的hello-world镜像。
很惊讶这个镜像的并不完全,完全没有发现任何一个地方有“hello world”的输出。然而好在,不是每一个Docker镜像都实现地这般草率。这个hello world的例子比较无聊,看看能不能找到更加有意思的。我们想从容器中服务一个页面,我打算使用Nginx,已经有一个现成的Nginx的容器了,因此我创建了个新的Dockerfile。Dockerfile包含了一系列如何指导Docker从一系列镜像中创建出一个容器的指令。这里提到的容器包含以下内容:
- FROM nginx
- COPY *.html /usr/share/nginx/html/
第一行设置了我们容器的基础镜像。第二行将本地的带有html后缀的文件拷贝到Nginx容器中WEB服务器的目录里。为了使用这个Dockerfile文件,我们需要创建一个Docker的镜像:
- /tmp/nginx$ docker build -t nginx_test .
- Sending build context to Docker daemon 3.072 kB
- Step 0 : FROM nginx
- latest: Pulling from library/nginx
- 843e2bded498: Pull complete
- 8c00acfb0175: Pull complete
- 426ac73b867e: Pull complete
- d6c6bbd63f57: Pull complete
- 4ac684e3f295: Pull complete
- 91391bd3c4d3: Pull complete
- b4587525ed53: Pull complete
- 0240288f5187: Pull complete
- 28c109ec1572: Pull complete
- 063d51552dac: Pull complete
- d8a70839d961: Pull complete
- ceab60537ad2: Pull complete
- Digest: sha256:9d0768452fe8f43c23292d24ec0fbd0ce06c98f776a084623d62ee12c4b7d58c
- Status: Downloaded newer image for nginx:latest
- ---> ceab60537ad2
- Step 1 : COPY *.html /usr/share/nginx/html/
- ---> ce25a968717f
- Removing intermediate container c45b9eb73bc7
- Successfully built ce25a968717f
Docker build命令开始将拉取已经构建好的Nginx容器。然后将我们的文件拷贝到容器里面,并且显示容器的hash值,这让它们很容易辨认。要运行这个容器我们可以运行:
- /tmp/nginx$ docker run --name simple_html -d -p 3001:80 -p 3002:443 nginx_test
这条命令让Docker运行nginxtest的容器,并且取名为simple_html。-d选项是为了让Docker在后台运行这条命令,并且最终-p选项是为了转发端口,这里需要将本地的3001端口映射到容器的80端口 - 即正常的web服务器端口。现在我们可以连接到web服务上了。如果我们打开chrome,访问localhost:3001就会看到:
居然不行,问题在于Docker没有意识到自己运行在虚拟机的环境里面,因此我们需要将vm的端口映射到我们本地机器上:
- Docker container:80 -> vm host:3001 -> OSX:3001
这个从虚拟机管理器里面可以轻松的搞定:
现在我们可以看到页面了:
这就是我们放在容器中的文件。好极了!现在我准备好尝试更复杂一点的容器了。
小贴士: 我注意到在虚拟机里面同时并行的运行Docker会整个让系统hang住。我怀疑同时跑两个虚拟工具可能让某个地方卡住产生了冲突的结果。我相信docker-machine的并行的支持正在在积极的解决中,0.5版本可能会看到。直到这之前,你可以参考:
http://kb.parallels.com/en/123356并且看看:
https://github.com/Parallels/docker-machine中对docker-machine的fork版本。
原文链接:Yet another intro to docker (翻译:钟最龙 校对:宋喻) 译文来自:DockOne.io