<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>王坤成的博客</title>
    <description>王坤成的博客
</description>
    <link>http://cocoakc.com/</link>
    <atom:link href="http://cocoakc.com/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Sun, 21 Aug 2022 14:02:08 +0000</pubDate>
    <lastBuildDate>Sun, 21 Aug 2022 14:02:08 +0000</lastBuildDate>
    <generator>Jekyll v3.9.2</generator>
    
      <item>
        <title>iOS-AVL</title>
        <description>&lt;p&gt;1、若它的左子树不为空，则左子树上所有的节点值都小于它的根节点值。&lt;/p&gt;

&lt;p&gt;2、若它的右子树不为空，则右子树上所有的节点值均大于它的根节点值。&lt;/p&gt;

&lt;p&gt;3、它的左右子树也分别可以充当为二叉查找树。&lt;/p&gt;

&lt;p&gt;例如：&lt;/p&gt;

&lt;p&gt;例如，我现在想要查找数值为14的节点。由于二叉查找树的特性，我们可以很快着找到它，其过程如下：&lt;/p&gt;

&lt;p&gt;1、和根节点9比较&lt;/p&gt;

&lt;p&gt;2、由于 14 &amp;gt; 9，所以14只可能存在于9的右子树中，因此查看右孩子13&lt;/p&gt;

&lt;p&gt;3、由于 14 &amp;gt; 13，所以继续查看13的右孩子15&lt;/p&gt;

&lt;p&gt;4、由于 14 &amp;lt; 15，所以14只可能存在于15的左孩子中，因此查找15的左孩子14&lt;/p&gt;

&lt;p&gt;5、这时候发现14正是自己查找的值，于是查找结束。&lt;/p&gt;

&lt;p&gt;这种查找二叉树的查找正是二分查找的思想，可以很快着找到目的节点，查找所需的最大次数等同于二叉查找树的高度。&lt;/p&gt;

&lt;p&gt;在插入的时候也是一样，通过一层一层的比较，最后找到适合自己的位置。&lt;/p&gt;

&lt;p&gt;初始的二叉查找树只有三个节点：&lt;/p&gt;

&lt;p&gt;然后我们按照顺序陆续插入节点 4，3，2，1，0。插入之后的结构如下：&lt;/p&gt;

&lt;p&gt;这是一种比查找二叉树还特别的树哦，这种树就可以帮助我们解决二叉查找树刚才的那种所有节点都倾向一边的缺点的。具有如下特性：&lt;/p&gt;

&lt;p&gt;具有二叉查找树的全部特性。&lt;/p&gt;

&lt;p&gt;每个节点的左子树和右子树的高度差至多等于1。&lt;/p&gt;

&lt;p&gt;例如：图一就是一颗AVL树了，而图二则不是(节点右边标的是这个节点的高度)。&lt;/p&gt;

&lt;p&gt;对于图二，因为节点9的左孩子高度为2，而右孩子高度为0。他们之间的差值超过1了。&lt;/p&gt;

&lt;p&gt;这种树就可以保证不会出现大量节点偏向于一边的情况了。&lt;/p&gt;

&lt;p&gt;听起来这种树还不错，可以对于图1，如果我们要插入一个节点3，按照查找二叉树的特性，我们只能把3作为节点4的左子树插进去，可是插进去之后，又会破坏了AVL树的特性，那我们那该怎么弄？&lt;/p&gt;

&lt;p&gt;右旋&lt;/p&gt;

&lt;p&gt;我们在进行节点插入的时候，可能会出现节点都倾向于左边的情况，例如：&lt;/p&gt;

&lt;p&gt;我们把这种倾向于左边的情况称之为 左-左型。这个时候，我们就可以对节点9进行右旋操作，使它恢复平衡。&lt;/p&gt;

&lt;p&gt;即：顺时针旋转两个节点，使得父节点被自己的左孩子取代，而自己成为自己的右孩子&lt;/p&gt;

&lt;p&gt;再举个例子：&lt;/p&gt;

&lt;p&gt;节点4和9高度相差大于1。由于是左孩子的高度较高，此时是左-左型，进行右旋。&lt;/p&gt;

&lt;p&gt;这里要注意，节点4的右孩子成为了节点6的左孩子了&lt;/p&gt;

&lt;p&gt;我找了个动图，尽量这个动图和上面例子的节点不一样。&lt;/p&gt;

&lt;p&gt;左旋&lt;/p&gt;

&lt;p&gt;左旋和右旋一样，就是用来解决当大部分节点都偏向右边的时候，通过左旋来还原。例如：&lt;/p&gt;

&lt;p&gt;我们把这种倾向于右边的情况称之为 右-右型。&lt;/p&gt;

&lt;p&gt;我也找了一张动图。&lt;/p&gt;

&lt;p&gt;例子讲解&lt;/p&gt;

&lt;p&gt;初始状态如下：&lt;/p&gt;

&lt;p&gt;然后我们主键插入如下数值：1,4,5,6,7,10,9,8&lt;/p&gt;

&lt;p&gt;插入 1&lt;/p&gt;

&lt;p&gt;左-左型，需要右旋调整。&lt;/p&gt;

&lt;p&gt;插入4&lt;/p&gt;

&lt;p&gt;继续插入 5&lt;/p&gt;

&lt;p&gt;右-右型，需要左旋转调整。&lt;/p&gt;

&lt;p&gt;继续插入6&lt;/p&gt;

&lt;p&gt;右-右型，需要进行左旋&lt;/p&gt;

&lt;p&gt;继续插入7&lt;/p&gt;

&lt;p&gt;右-右型，需要进行左旋&lt;/p&gt;

&lt;p&gt;继续插入10&lt;/p&gt;

&lt;p&gt;继续插入9&lt;/p&gt;

&lt;p&gt;出现了这种情况怎么办呢?对于这种  右-左型 的情况，单单一次左旋或右旋是不行的，下面我们先说说如何处理这种情况。&lt;/p&gt;

&lt;p&gt;这种我们就把它称之为 右-左 型吧。处理的方法是先对节点10进行右旋把它变成右-右型。&lt;/p&gt;

&lt;p&gt;然后在进行左旋。&lt;/p&gt;

&lt;p&gt;所以对于这种 右-左型的，我们需要进行一次右旋再左旋。&lt;/p&gt;

&lt;p&gt;同理，也存在 左-右型的，例如：&lt;/p&gt;

&lt;p&gt;对于左-右型的情况和刚才的 右-左型相反，我们需要对它进行一次左旋，再右旋。&lt;/p&gt;

&lt;p&gt;回到刚才那道题&lt;/p&gt;

&lt;p&gt;对它进行右旋再左旋。&lt;/p&gt;

&lt;p&gt;到此，我们的插入就结束了。&lt;/p&gt;

&lt;p&gt;总结一下&lt;/p&gt;

&lt;p&gt;在插入的过程中，会出现一下四种情况破坏AVL树的特性，我们可以采取如下相应的旋转。&lt;/p&gt;

&lt;p&gt;1、左-左型：做右旋。&lt;/p&gt;

&lt;p&gt;2、右-右型：做左旋转。&lt;/p&gt;

&lt;p&gt;3、左-右型：先做左旋，后做右旋。&lt;/p&gt;

&lt;p&gt;4、右-左型：先做右旋，再做左旋。&lt;/p&gt;

&lt;p&gt;不知道大家发现规律没，这个规则还是挺好记。&lt;/p&gt;

&lt;p&gt;代码实现&lt;/p&gt;

&lt;p&gt;//定义节点
class AvlNode {
int data;
AvlNode lchild;//左孩子
AvlNode rchild;//右孩子
int height;//记录节点的高度
}&lt;/p&gt;

&lt;p&gt;//在这里定义各种操作
public class AVLTree{
//计算节点的高度
static int height(AvlNode T) {
if (T == null) {
return -1;
}else{
return T.height;
}
}&lt;/p&gt;

&lt;p&gt;//左左型，右旋操作
static AvlNode R_Rotate(AvlNode K2) {
AvlNode K1;&lt;/p&gt;

&lt;p&gt;//进行旋转
K1 = K2.lchild;
K2.lchild = K1.rchild;
K1.rchild = K2;&lt;/p&gt;

&lt;p&gt;//重新计算节点的高度
K2.height = Math.max(height(K2.lchild), height(K2.rchild)) + 1;
K1.height = Math.max(height(K1.lchild), height(K1.rchild)) + 1;&lt;/p&gt;

&lt;p&gt;return K1;
}&lt;/p&gt;

&lt;p&gt;//进行左旋
static AvlNode L_Rotate(AvlNode K2) {
AvlNode K1;&lt;/p&gt;

&lt;p&gt;K1 = K2.rchild;
K2.rchild = K1.lchild;
K1.lchild = K2;&lt;/p&gt;

&lt;p&gt;//重新计算高度
K2.height = Math.max(height(K2.lchild), height(K2.rchild)) + 1;
K1.height = Math.max(height(K1.lchild), height(K1.rchild)) + 1;&lt;/p&gt;

&lt;p&gt;return K1;
}&lt;/p&gt;

&lt;p&gt;//左-右型，进行右旋，再左旋
static AvlNode R_L_Rotate(AvlNode K3) {
//先对其孩子进行左旋
K3.lchild = R_Rotate(K3.lchild);
//再进行右旋
return L_Rotate(K3);
}&lt;/p&gt;

&lt;p&gt;//右-左型，先进行左旋，再右旋
static AvlNode L_R_Rotate(AvlNode K3) {
//先对孩子进行左旋
K3.rchild = L_Rotate(K3.rchild);
//在右旋
return R_Rotate(K3);
}&lt;/p&gt;

&lt;p&gt;//插入数值操作
static AvlNode insert(int data, AvlNode T) {
if (T == null) {
T = new AvlNode();
T.data = data;
T.lchild = T.rchild = null;
} else if(data &amp;lt; T.data) {
//向左孩子递归插入
T.lchild = insert(data, T.lchild);
//进行调整操作
//如果左孩子的高度比右孩子大2
if (height(T.lchild) - height(T.rchild) == 2) {
//左-左型
if (data &amp;lt; T.lchild.data) {
T = R_Rotate(T);
} else {
//左-右型
T = R_L_Rotate(T);
}
}
} else if (data &amp;gt; T.data) {
T.rchild = insert(data, T.rchild);
//进行调整
//右孩子比左孩子高度大2
if(height(T.rchild) - height(T.lchild) == 2)
//右-右型
if (data &amp;gt; T.rchild.data) {
T = L_Rotate(T);
} else {
T = L_R_Rotate(T);
}
}
//否则，这个节点已经在书上存在了，我们什么也不做&lt;/p&gt;

&lt;p&gt;//重新计算T的高度
T.height = Math.max(height(T.lchild), height(T.rchild)) + 1;
return T;
}
}
提示：可以左右拉动&lt;/p&gt;

&lt;p&gt;希望通过这种漫画的形式，能够让你们更加容易读懂一些算法或数据结构。&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/wkrelease&quot;&gt;GitHub&lt;/a&gt;&lt;/p&gt;

</description>
        <pubDate>Mon, 28 Oct 2019 00:00:00 +0000</pubDate>
        <link>http://cocoakc.com/2019/10/28/ios-AVL.html</link>
        <guid isPermaLink="true">http://cocoakc.com/2019/10/28/ios-AVL.html</guid>
        
        <category>iOS</category>
        
        
        <category>技术</category>
        
      </item>
    
      <item>
        <title>iOS-逆向</title>
        <description>&lt;h2 id=&quot;用途&quot;&gt;用途&lt;/h2&gt;

&lt;p&gt;在使用之前，大家关心的都是它的功能，可以做什么。那么MonkeyDev这个工具可以做什么呢？总结来说可以做如下这些事情:&lt;/p&gt;

&lt;p&gt;可以使用Xcode开发CaptainHook Tweak、Logos Tweak 和 Command-line Tool，在越狱机器开发插件，这是原来iOSOpenDev功能的迁移和改进。
只需拖入一个砸壳应用，自动集成Reveal、Cycript和注入的动态库并重签名安装到非越狱机器。
支持调试自己编写的动态库和第三方App
支持通过CocoaPods第三方应用集成SDK以及非越狱插件，简单来说就是通过CocoaPods搭建了一个非越狱插件商店。
大概了解了之后下面就通过具体的实际应用来体会它的强大之处吧。&lt;/p&gt;

&lt;h2 id=&quot;环境准备&quot;&gt;环境准备&lt;/h2&gt;

&lt;p&gt;在使用之前首先是环境的配置，如果配置不对的话，可能会出一些奇怪的问题，你也可以结合Wiki来操作。&lt;/p&gt;

&lt;p&gt;安装最新的theos
git clone –recursive https://github.com/theos/theos.git /opt/theos
安装ldid
brew install ldid
如果是用于越狱开发，需要配置免密码登录越狱设备，如果没有越狱机器可以跳过这步。
ssh-keygen -t rsa -P ‘’
ssh-copy-id -i /Users/username/.ssh/id_rsa root@ip
安装&lt;/p&gt;

&lt;p&gt;你可以通过如下命令选择指定的Xcode进行安装，也可以默认安装。&lt;/p&gt;

&lt;p&gt;指定Xcode安装:
sudo xcode-select -s /Applications/Xcode-xxx.app
默认安装的Xcode:
xcode-select -p
执行安装命令:
git clone https://github.com/AloneMonkey/MonkeyDev.git
cd MonkeyDev/bin
sudo ./md-install
如需卸载，执行卸载命令:
sudo ./md-uninstall
如需更新，执行更新命令:
sudo ./md-update
模块介绍&lt;/p&gt;

&lt;p&gt;安装完成之后，打开Xcode，点击File - New - Project…，选择iOS滑动到最下方可以看到MonkeyDev提供的模块:&lt;/p&gt;

&lt;h2 id=&quot;介绍下这几个模块的用途&quot;&gt;介绍下这几个模块的用途:&lt;/h2&gt;

&lt;p&gt;越狱模块&lt;/p&gt;

&lt;p&gt;CaptainHook Tweak
使用CaptainHook提供的头文件进行OC函数的Hook，以及属性的获取。&lt;/p&gt;

&lt;p&gt;Logos Tweak
使用theos提供的logify.pl工具将.xm文件转成.mm文件进行编译，默认集成CydiaSubstrate，可以使用MSHookMessageEx和MSHookFunction来Hook OC函数和指定地址。&lt;/p&gt;

&lt;p&gt;Command-line Tool
可以直接创建运行于越狱设备的命令行工具&lt;/p&gt;

&lt;p&gt;非越狱模块&lt;/p&gt;

&lt;p&gt;MonkeyApp
这是自动给第三方应用集成Reveal、Cycript和注入dylib的模块，支持调试dylib和第三方应用，支持Pod给第三放应用集成SDK，只需要准备一个砸壳后的ipa或者app文件即可。&lt;/p&gt;

&lt;p&gt;功能介绍&lt;/p&gt;

&lt;p&gt;关于CaptainHook Tweak、Logos Tweak 和 Command-line Tool的使用这里不再介绍，有问题可以查看项目Wiki&lt;/p&gt;

&lt;p&gt;下面主要介绍MonkeyApp的使用，开启你的非越狱插件开发之旅~&lt;/p&gt;

&lt;p&gt;准备&lt;/p&gt;

&lt;p&gt;在开始使用前，需要准备一个砸壳后的应用，可以使用越狱手机砸壳，然后获取ipa或app，没有越狱手机直接从某助手下载越狱应用即可。&lt;/p&gt;

&lt;p&gt;创建项目&lt;/p&gt;

&lt;p&gt;点击File - New - Project…创建iOS项目，选择MonkeyApp。&lt;/p&gt;

&lt;p&gt;创建完成之后，你会得到一个这样的工程:&lt;/p&gt;

&lt;p&gt;这里我创建的项目名字就是MonkeyApp，所以下面对应的都是MonkeyApp，你自己创建的由你的项目名字而定! 另外Xcode 8需要另外在App里面增加动态库的依赖，如下:&lt;/p&gt;

&lt;p&gt;MonkeyAppDylib这个是将被注入目标App的动态库，你自己要hook的代码可以在MonkeyAppDylib.m文件里面写，我在里面写了一些Demo代码，直接运行即可看到效果，支持OC runtime的HOOK，C函数的fishhook。&lt;/p&gt;

&lt;p&gt;AntiAntiDebug这个里面是反反调试的代码。&lt;/p&gt;

&lt;p&gt;fishhook这个是自动集成的fishhook模块。&lt;/p&gt;

&lt;p&gt;下面Framewroks已经自动集成了Reveal.framework和Cycript.framework。&lt;/p&gt;

&lt;p&gt;拖入砸壳应用编译&lt;/p&gt;

&lt;p&gt;打开某助手选择应用游戏里面的越狱应用，下载一个应用就是已经砸壳了的。&lt;/p&gt;

&lt;p&gt;然后打开TargetApp目录，拷贝ipa文件到当前目录下面，如下图所示:&lt;/p&gt;

&lt;p&gt;然后点击运行即可，运行后可以从控制台看到动态库已经注入成功，Reveal已经成功加载！当然手机上面也运行起来了！&lt;/p&gt;

&lt;p&gt;打开Mac上的Reveal即可查看应用的界面结构啦！如下图所示:&lt;/p&gt;

&lt;p&gt;默认还集成了Cycript，从Cycript官网下载SDK，然后进去SDK目录运行如下命令即可:&lt;/p&gt;

&lt;p&gt;./cycript -r iphoneip:6666&lt;/p&gt;

&lt;p&gt;获取微信消息&lt;/p&gt;

&lt;p&gt;下面以一个简单获取微信收到的消息为例，来进一步介绍它的使用，首先打开MonkeyAppDylib.m文件，在最下面写入如下代码:&lt;/p&gt;

&lt;p&gt;@interface CMessageWrap
@property (nonatomic, strong) NSString* m_nsContent;
@property (nonatomic, assign) NSInteger m_uiMessageType;
@end
CHDeclareClass(CMessageMgr)&lt;/p&gt;

&lt;p&gt;CHMethod2(void, CMessageMgr, AsyncOnAddMsg, NSString&lt;em&gt;, msg, MsgWrap, CMessageWrap&lt;/em&gt;, msgWrap){
    NSString* content = [msgWrap m_nsContent];
    if([msgWrap m_uiMessageType] == 1){
        NSLog(@”收到消息: %@”, content);
    }
    CHSuper2(CMessageMgr, AsyncOnAddMsg, msg, MsgWrap, msgWrap);
}&lt;/p&gt;

&lt;p&gt;CHConstructor{
    CHLoadLateClass(CMessageMgr);
    CHClassHook2(CMessageMgr, AsyncOnAddMsg, MsgWrap);
}
然后重新运行就能看到效果了:&lt;/p&gt;

&lt;p&gt;然后就可以愉快的开发非越狱插件了，还可以直接调试!&lt;/p&gt;

&lt;p&gt;使用CocoaPods集成SDK&lt;/p&gt;

&lt;p&gt;MonkeyDev还支持CocoaPods给第三方应用集成SDK，新建Podfile，写入:&lt;/p&gt;

&lt;p&gt;target ‘MonkeyAppDylib’ do
     pod ‘FLEX’
end
这里的Target要设置为动态库而不是App，然后执行Pod install。然后将如下选项改回Yes。&lt;/p&gt;

&lt;p&gt;在MonkeyAppDylib.m文件中加入SDK初始化代码:&lt;/p&gt;

&lt;p&gt;#import &amp;lt;FLEX/FLEXManager.h&amp;gt;&lt;/p&gt;

&lt;p&gt;void initCycriptServer(){
    [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidFinishLaunchingNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
        [[FLEXManager sharedManager] showExplorer];
        CYListenServer(6666);
    }];
}
运行效果如下:&lt;/p&gt;

&lt;p&gt;非越狱插件商店&lt;/p&gt;

&lt;p&gt;既然可以支持CocoaPods了，那么完全可以将自己写的非越狱插件传到CocoaPods，然后通过pod一键安装！&lt;/p&gt;

&lt;p&gt;下面就将上面写的获取微信消息插件放到CocoaPods，新建Cocoa Touch Framework项目，然后增加头文件CaptainHook.h和自己的源文件PrintWXMessage.m，并将上面的代码拷贝过来，如下图所示:&lt;/p&gt;

&lt;p&gt;然后生成framework弄成zip包(zip包需要包含模拟器和真机的架构才能通过本地验证)，编辑PrintWXMessage.podspec文件内容如下:&lt;/p&gt;

&lt;p&gt;Pod::Spec.new do |spec|
  spec.name             = “PrintWXMessage”
  spec.version          = “1.0.0”
  spec.summary          = “Print WX Message for MonkeyDev”
  spec.description      = «-DESC
                          - Print WX Message for MonkeyDev
                        DESC&lt;/p&gt;

&lt;p&gt;spec.homepage         = “https://github.com/AloneMonkey/MonkeyDev”&lt;/p&gt;

&lt;p&gt;spec.license          = { :type =&amp;gt; “BSD”, :file =&amp;gt; “LICENSE” }
  spec.author           = { “AloneMonkey” =&amp;gt; “liupeiqing1993@163.com” }
  spec.social_media_url = “http://weibo.com/xiaoqing28”
  spec.platform         = :ios, “8.0”
  spec.source           = { :http =&amp;gt; “https://github.com/AloneMonkey/MonkeyDevPod/raw/master/PrintWXMessage/LatestBuild/PrintWXMessage.zip”}
  spec.vendored_frameworks = “PrintWXMessage.framework”
end
这里source直接写的是zip包的地址，里面就是笔者生成的framework动态库。&lt;/p&gt;

&lt;p&gt;增加私有CocosPods:&lt;/p&gt;

&lt;p&gt;pod repo add MonkeyDevSpecs https://github.com/AloneMonkey/MonkeyDevSpecs.git
将PrintWXMessage包发布到私有Pod:&lt;/p&gt;

&lt;p&gt;pod repo push MonkeyDevSpecs PrintWXMessage.podspec
修改Podfile文件内容如下，然后pod install安装，并且把原来写在MonkeyAppDylib.m的打印微信消息的代码删除。&lt;/p&gt;

&lt;p&gt;source ‘https://github.com/AloneMonkey/MonkeyDevSpecs.git’&lt;/p&gt;

&lt;p&gt;target ‘MonkeyAppDylib’ do
     pod ‘PrintWXMessage’
end
~ MonkeyApp pod install
Cloning spec repo &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alonemonkey&lt;/code&gt; from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https://github.com/AloneMonkey/MonkeyDevSpecs.git&lt;/code&gt;
Analyzing dependencies
Downloading dependencies
Installing PrintWXMessage (1.0.0)
Generating Pods project
Integrating client project&lt;/p&gt;

&lt;p&gt;[!] Please close any current Xcode sessions and use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MonkeyPod.xcworkspace&lt;/code&gt; for this project from now on.
Pod installation complete! There is 1 dependency from the Podfile and 1 total pod installed.
运行即可看到插件已经完美集成成功！！！&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/wkrelease&quot;&gt;GitHub&lt;/a&gt;&lt;/p&gt;

</description>
        <pubDate>Fri, 28 Jul 2017 00:00:00 +0000</pubDate>
        <link>http://cocoakc.com/2017/07/28/ios-%E9%80%86%E5%90%91.html</link>
        <guid isPermaLink="true">http://cocoakc.com/2017/07/28/ios-%E9%80%86%E5%90%91.html</guid>
        
        <category>iOS</category>
        
        
        <category>技术</category>
        
      </item>
    
      <item>
        <title>hello kc</title>
        <description>&lt;p&gt;“我刚才在星巴克看到一个喝咖啡的家伙，没玩手机，没拍照发朋友圈，没带笔记本电脑，也没有iPad，更没有和其他人谈事情，他只是坐在那里默默喝他的咖啡，不像个正常人。”&lt;/p&gt;
</description>
        <pubDate>Wed, 19 Jul 2017 00:00:00 +0000</pubDate>
        <link>http://cocoakc.com/2017/07/19/the-life.html</link>
        <guid isPermaLink="true">http://cocoakc.com/2017/07/19/the-life.html</guid>
        
        <category>Essay</category>
        
        
        <category>生活</category>
        
      </item>
    
      <item>
        <title>你明明是碌碌无为，快别说什么平凡可贵</title>
        <description>&lt;p&gt;在我们中间，90%的人都会平庸到老。&lt;/p&gt;

&lt;p&gt;每天上着日复一日的班，拿着不高不低的工资，坐同一班公交，车上的人们低头看手机，面无表情。&lt;/p&gt;

&lt;p&gt;有一句话触目惊心： “很多人在20多岁就死了，只是到了70岁才埋。”&lt;/p&gt;

&lt;p&gt;他们早就在现实面前举手投降，失去了好奇心和探索。他们不相信诗和远方。他们只是勉强活着，从未真正热爱过生活。&lt;/p&gt;

&lt;p&gt;这个世界波澜壮阔，只一条30度的北纬线上就传奇良多。可惜我们大多数人都疲于奔命，看不到这浩大江湖。&lt;/p&gt;

&lt;p&gt;当你盯着电脑，重复机械地做报表时，在遥远的云南镇雄，神秘的天坑底，正有人过着惬意的桃源生活。&lt;/p&gt;

&lt;p&gt;没有人知道天坑究竟是怎么来的；就像没人能解释得清，对着天坑悬崖上的一个小洞吹气，整个悬崖都会响起一阵悲伤的呜咽；也没有人清楚，在天坑里大喊一声“我爱你”，竟传来世界上最长久的回声。&lt;/p&gt;

&lt;p&gt;五十多年前，几户人家搬来，在这里开垦田地，挖掘水源，燃起炊烟，从此再未离开。&lt;/p&gt;

&lt;p&gt;在我们排队摇号买房子，一言不合矛盾四起的时候，他们扛起锄头，收获了一季的粮食，开辟了一块新的土地。&lt;/p&gt;

&lt;p&gt;这个世界总有一些迷人的未知；这世界上，也不只一种活法。&lt;/p&gt;

&lt;p&gt;当我们为了一份糊口的工资出卖理想时，在人迹罕至的怒江峡谷，一群独龙族的女人却为了古老的信仰纹了面。&lt;/p&gt;

&lt;p&gt;这个只有几千人生活的河谷里，每一个少女都要经历一番青春的阵痛——以荆棘刺出图案，以特殊的染料着色，从此脸上永久地刻上了神秘又美丽的纹样。&lt;/p&gt;

&lt;p&gt;当地有一个悠久的传说：纹面是为了死后与灵魂相认。是的，在这个我们以为信仰缺失的时代，依然有人坚信灵魂的存在。&lt;/p&gt;

&lt;p&gt;这就是旅行的意义吧，不是为了换个地方，而是为了换种思想。&lt;/p&gt;

&lt;p&gt;当我们热到窝在空调房里一动不动时，浙江千岛湖底，一座千年古城安静地沉睡在那里。&lt;/p&gt;

&lt;p&gt;56年前，城里的居民全部搬离，整个小镇慢慢被湖水吞没。无数精美的建筑，别具特色的民房、砖雕和石刻，成了再难见到的谜题。&lt;/p&gt;

&lt;p&gt;在我们逛商场、看电影、和上司争吵时，没有人意识到，有些很壮美的景色和很伟大的奇迹，正在飞快地趋于消亡。在你还没来得及见它一眼，甚至尚未意识到它存在的时候，就已经永久地离开。&lt;/p&gt;

&lt;p&gt;而你站在拥挤的人潮里，对这巨大的失去一无所知。&lt;/p&gt;

&lt;p&gt;当我们挤地铁被咸猪手，怀疑人性时，有人正在深入撒哈拉沙漠的杰贝尔伊罗考古点探寻人类的起源。&lt;/p&gt;

&lt;p&gt;当我们为了明天的一个面试忐忑不安时，NASA宇航中心，一位老宇航员，正缓缓讲述着第一次离开地球时的激动。&lt;/p&gt;

&lt;p&gt;当我们以为人生不过如此时，这些灵动的生命和新鲜的生活正在一条30度的北纬线上有滋味地进行着。&lt;/p&gt;

&lt;p&gt;其实我们每个人都处在人生的经纬上。这一生不断行走、持续寻找。&lt;/p&gt;

&lt;p&gt;寻找美景、寻找自我。&lt;/p&gt;

&lt;p&gt;告别行色匆匆和千篇一律的行程，寻找一种不凡的生活。&lt;/p&gt;

&lt;p&gt;山本耀司有一句话：“时尚不会让你变得性感，你的经历可以。”&lt;/p&gt;

&lt;p&gt;走出来，打破固有的认知，让一种生活触碰另一种生活，一种文化撞击另一种文化，也给自己一个超越自己的机会。&lt;/p&gt;

&lt;p&gt;那些寻找的经过，正是你拥有不凡的经历。那些你经历的纬度，决定了你的人生态度。&lt;/p&gt;

</description>
        <pubDate>Tue, 18 Jul 2017 00:00:00 +0000</pubDate>
        <link>http://cocoakc.com/2017/07/18/the-importent-of-writing.html</link>
        <guid isPermaLink="true">http://cocoakc.com/2017/07/18/the-importent-of-writing.html</guid>
        
        <category>Essay</category>
        
        
        <category>生活</category>
        
      </item>
    
      <item>
        <title>你们只管逃离北上广</title>
        <description>&lt;h3 id=&quot;你们只管逃离北上广我偏要留在这&quot;&gt;你们只管逃离北上广，我偏要留在这&lt;/h3&gt;

&lt;p&gt;有人说，北上广人情冷漠，每个人都很孤独，可是我恰好喜欢北上广的冷漠。&lt;/p&gt;

&lt;p&gt;. 正因为每个人都冷漠，你才能自由自在的活着；
. 正义为这样的冷漠才削弱了裙带关系，让你的才华有一席之地；
. 也正是因为这样的冷漠，才让你一个人吃饭工作回家的你显得不那么突兀。&lt;/p&gt;

&lt;h3 id=&quot;小城市的邻里街坊有一种无来由的怜悯感&quot;&gt;小城市的邻里街坊有一种无来由的怜悯感。&lt;/h3&gt;

&lt;p&gt;. 你二十几岁没结婚，他们觉得你可怜；
. 你结婚几年没孩子，他们怀疑你有隐疾觉得腻可怜；
. 你做自由职业，他们同情你没有铁饭碗觉得你可怜。
. 他们一代一代一辈一辈重复着固定的轨迹一样的生活，只要跟他们固定思维有偏差，你就会被当成异类指指点点。&lt;/p&gt;

&lt;h3 id=&quot;我们一路奋战为的不是变成别人位的不是改变世界而是不让世界改变能够用自己的力量平稳地站在大地上不用卑躬屈膝不用容忍傻逼无所顾忌的选择自己所喜欢的有权利大声说话有能力保护自己想保护的人&quot;&gt;我们一路奋战，为的不是变成别人，位的不是改变世界，而是不让世界改变，能够用自己的力量平稳地站在大地上，不用卑躬屈膝，不用容忍傻逼，无所顾忌的选择自己所喜欢的，有权利大声说话，有能力保护自己想保护的人。&lt;/h3&gt;
</description>
        <pubDate>Thu, 13 Jul 2017 00:00:00 +0000</pubDate>
        <link>http://cocoakc.com/2017/07/13/life-week.html</link>
        <guid isPermaLink="true">http://cocoakc.com/2017/07/13/life-week.html</guid>
        
        <category>life</category>
        
        
        <category>生活</category>
        
      </item>
    
      <item>
        <title>小程序 学习 - 预览大图</title>
        <description>&lt;h2 id=&quot;为image绑定事件&quot;&gt;为image绑定事件&lt;/h2&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;image src=&quot;https://app.xxx.com/a.jpg&quot; bindload=&quot;imageLoad&quot; bindtap=&quot;previewImage&quot; mode=&quot;aspectFill&quot; data-index=&quot;&quot;&amp;gt;&amp;lt;/image&amp;gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;实现方法&quot;&gt;实现方法&lt;/h2&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
  previewImage: function (e) {
    var currentIndex = e.target.dataset.index;
    wx.previewImage({
      current: this.data.urlList[currentIndex], // 当前显示图片的http链接  
      urls: this.data.urlList // 需要预览的图片http链接列表  
    })
  },


&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;currentIndex 获取index&lt;/p&gt;

&lt;p&gt;current 为当前显示图片的http链接&lt;/p&gt;

&lt;p&gt;urls 需要预览的图片http链接列表&lt;/p&gt;

&lt;h2 id=&quot;这些在官方文档里写的十分简明&quot;&gt;这些在官方文档里写的十分简明&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://mp.weixin.qq.com/debug/wxadoc/dev/api/media-picture.html#wxpreviewimageobject&quot;&gt;微信小程序官方文档&lt;/a&gt;&lt;/p&gt;

</description>
        <pubDate>Tue, 11 Jul 2017 00:00:00 +0000</pubDate>
        <link>http://cocoakc.com/2017/07/11/setup-wechat-%E5%B0%8F%E7%A8%8B%E5%BA%8F.html</link>
        <guid isPermaLink="true">http://cocoakc.com/2017/07/11/setup-wechat-%E5%B0%8F%E7%A8%8B%E5%BA%8F.html</guid>
        
        <category>小程序</category>
        
        
        <category>技术</category>
        
      </item>
    
      <item>
        <title>Docker 使用总结</title>
        <description>&lt;h2 id=&quot;docker-基本概念&quot;&gt;Docker 基本概念&lt;/h2&gt;

&lt;h3 id=&quot;镜像-image&quot;&gt;镜像 Image&lt;/h3&gt;

&lt;p&gt;镜像是一些打包好的已有的环境，可以被用来启动和创建容器，本身不能被直接修改。&lt;/p&gt;

&lt;h3 id=&quot;容器-container&quot;&gt;容器 Container&lt;/h3&gt;

&lt;p&gt;容器是镜像的实例化，是可以修改的，但是都是临时修改。&lt;/p&gt;

&lt;h3 id=&quot;容器启动过程&quot;&gt;容器启动过程&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;检查本地是否存在指定的镜像，不存在就从公有仓库下载&lt;/li&gt;
  &lt;li&gt;利用镜像创建并启动一个容器&lt;/li&gt;
  &lt;li&gt;分配一个文件系统，并在只读的镜像层外面挂载一层可读写层&lt;/li&gt;
  &lt;li&gt;从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去&lt;/li&gt;
  &lt;li&gt;从地址池配置一个 ip 地址给容器&lt;/li&gt;
  &lt;li&gt;执行用户指定的应用程序&lt;/li&gt;
  &lt;li&gt;执行完毕后容器被终止&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;docker-常用命令&quot;&gt;Docker 常用命令&lt;/h2&gt;

&lt;h3 id=&quot;image-操作&quot;&gt;Image 操作&lt;/h3&gt;

&lt;h4 id=&quot;基本操作&quot;&gt;基本操作&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;显示本地所有镜像&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker images
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;搜索一个image&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker search image_name
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;下载image&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker pull image_name
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;删除镜像&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker rmi image_name
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;显示镜像历史&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker history image_name
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;制作镜像&quot;&gt;制作镜像&lt;/h4&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker build -t image_name DockerfilePath
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这里DockerfilePath是Context上下文目录，在创建的时候会全部上传到Docker Server端，所以这个目录不要太大&lt;/p&gt;

&lt;h4 id=&quot;迁移镜像&quot;&gt;迁移镜像&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;保存镜像到文件&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker save image_name -o file.tar
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;加载一个tar包的镜像&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker load -i file.tar
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;container-操作&quot;&gt;Container 操作&lt;/h3&gt;

&lt;h4 id=&quot;显示相关&quot;&gt;显示相关&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;查看运行中的容器&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker ps

# 一行显示全部容器
docker ps | less -S

# 最近一次启动
docker ps -l

# 列出所有容器
docker ps -a
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;显示一个运行的容器里面的进程信息&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker top cid
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;显示容器详细信息&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker inspect cid
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;查看容器日志&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker logs cid

# 实时查看日志输出
docker logs -f cid
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;查看容器更改&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker diff cid
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;查看容器root用户密码&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker logs cid 2&amp;gt;&amp;amp;1 | grep '^User: ' | tail -n1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;运行相关&quot;&gt;运行相关&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;启动容器并执行一个命令（交互）&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# -t 终端
# -i 交互操作
docker run -it ubuntu /bin/bash

# 运行一个hello word然后就自动关闭
docker run image_name echo &quot;hello word&quot;

# 命名并启动容器
docker run --name test ubuntu

# 后台运行一个容器
docker run -d -it ubuntu

# 映射端口
docker run -p 8080:8080 ubuntu

# 挂载volumn
docker run -v ./test:/var/www

# container 内 root 拥有真正root权限
docker run --privileged=false

# 启动完镜像后自动删除
docker run -it --rm ubuntu bash
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;附着到正在运行的容器, 附着完以后退出会导致容器也终止&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker attach cid
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;进入正在运行的 container 并且执行&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker exec -it 839a6cfc9496 /bin/bash
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;在容器中运行一段程序&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker run ubuntu apt-get update
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;拷贝文件出来&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker cp cid:/container_path to_path  
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;修改容器&quot;&gt;修改容器&lt;/h4&gt;

&lt;p&gt;image相当于类，container相当于实例，不过可以动态给实例安装新软件，然后把这个container用commit命令固化成一个image&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;提交一个commit&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker commit cid new_image_name
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;删除容器&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker rm cid

# 强制删除
docker rm -f cid

# 删除所有容器
docker rm `docker ps -a -q`
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;状态修改&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker start/stop/kill/restart cid
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;更改名字&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker rename old new
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;链接容器&quot;&gt;链接容器&lt;/h4&gt;

&lt;p&gt;sonar容器连接到mysql容器，并将mysql容器重命名为db。这样，sonar容器就可以使用db的相关的环境变量了。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker run -it --name sonar -d -link mysql:db tpires/sonar-server
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;仓库操作&quot;&gt;仓库操作&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;登录到docker仓库&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker login
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;上传镜像&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker push new_image_name
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;dockerfile-常用命令&quot;&gt;Dockerfile 常用命令&lt;/h2&gt;

&lt;p&gt;有了 Dockerfile 可以自定义一些自己需要的镜像，在熟悉了 Docker 基本操作，然后使用过一些别人提供好的镜像以后，难免需要自己修改一部分。&lt;/p&gt;

&lt;h3 id=&quot;from&quot;&gt;FROM&lt;/h3&gt;

&lt;p&gt;指定基础镜像。例如：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;ubuntu&lt;/li&gt;
  &lt;li&gt;nginx&lt;/li&gt;
  &lt;li&gt;redis&lt;/li&gt;
  &lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;FROM nginx
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;run&quot;&gt;RUN&lt;/h3&gt;

&lt;p&gt;执行一些命令&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;RUN echo '&amp;lt;h1&amp;gt;Hello, Docker!&amp;lt;/h1&amp;gt;' &amp;gt; /usr/share/nginx/html/index.html
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;每个RUN命令都会在容器中建立一层，所以尽量合并多个命令。例如&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;RUN buildDeps='gcc libc6-dev make' \
    &amp;amp;&amp;amp; apt-get update \
    &amp;amp;&amp;amp; apt-get install -y $buildDeps \
    ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;copy&quot;&gt;COPY&lt;/h3&gt;

&lt;p&gt;复制文件到指定目录 source -&amp;gt; target&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;COPY ./package.json /usr/src/app
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;cmd&quot;&gt;CMD&lt;/h3&gt;

&lt;p&gt;容器的启动命令&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;CMD [&quot;nginx&quot;, &quot;-g&quot;, &quot;daemon off;&quot;]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这个命令可以在启动时被覆盖。另外它也可以为 ENTRYPOINT 提供参数。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;CMD 理论上只能执行一次，如果想要执行两个命令，需要使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&lt;/code&gt; 来连接两个命令，或者使用一个bash文件。更为高级一点的方法是用supervisor来管理&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;entrypoint&quot;&gt;ENTRYPOINT&lt;/h3&gt;

&lt;p&gt;ENTRYPOINT 和 CMD 有一部分重复工作，但是 ENTRYPOINT 可以让容器像软件一样执行。例如&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ENTRYPOINT /bin/echo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在容器启动时，之后增加的内容都属于这个命令的参数。&lt;/p&gt;

&lt;h3 id=&quot;env&quot;&gt;ENV&lt;/h3&gt;

&lt;p&gt;设置环境变量。&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ENV key value&lt;/code&gt;&lt;/p&gt;

&lt;h3 id=&quot;arg&quot;&gt;ARG&lt;/h3&gt;

&lt;p&gt;构建参数，在容器启动后不会存在。&lt;/p&gt;

&lt;h3 id=&quot;volume&quot;&gt;VOLUME&lt;/h3&gt;

&lt;p&gt;定义匿名卷，以免用户忘了挂载volumn，导致大量写入。这个 Volume 在容器启动前可以添加内容，但是并不是实际操作用户挂载的内容。在用户挂载完 volume 后，原来写在这里的内容会被复制到用户挂载的目录。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;注意：在 VOLUME 命令之后对这个目录的所有操作，将被忽略。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;expose&quot;&gt;EXPOSE&lt;/h3&gt;

&lt;p&gt;申明端口，可以用来默认映射端口，以及容器间互通。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;EXPOSE 22 80
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;workdir&quot;&gt;WORKDIR&lt;/h3&gt;

&lt;p&gt;指定工作目录。不仅是当前 docker 中的目录，同时也是运行容器时刚刚登录以后的目录。&lt;/p&gt;

&lt;h3 id=&quot;user&quot;&gt;USER&lt;/h3&gt;

&lt;p&gt;指定当前用户。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;RUN groupadd -r redis &amp;amp;&amp;amp; useradd -r -g redis redis
USER redis
RUN [ &quot;redis-server&quot; ]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;healthcheck&quot;&gt;HEALTHCHECK&lt;/h3&gt;

&lt;p&gt;健康检查&lt;/p&gt;

&lt;h3 id=&quot;onbuild&quot;&gt;ONBUILD&lt;/h3&gt;

&lt;p&gt;当此容器作为别的容器的基础容器时操作内容&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;FROM node:slim
RUN &quot;mkdir /app&quot;
WORKDIR /app
ONBUILD COPY ./package.json /app
ONBUILD RUN [ &quot;npm&quot;, &quot;install&quot; ]
ONBUILD COPY . /app/
CMD [ &quot;npm&quot;, &quot;start&quot; ]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;docker-compose-常用指令&quot;&gt;Docker-compose 常用指令&lt;/h2&gt;

&lt;h3 id=&quot;depends_on&quot;&gt;depends_on&lt;/h3&gt;

&lt;p&gt;这个不仅可以保证build的先后顺序，还可以省去links的设置&lt;/p&gt;

&lt;h3 id=&quot;links&quot;&gt;links&lt;/h3&gt;

&lt;p&gt;和docker run命令一致，主要原因是在每次新开启container的时候，port可能会变，所以有了这个设置可以保证每次都可以绑定到正确的值。&lt;/p&gt;

&lt;h2 id=&quot;实例操作&quot;&gt;实例操作&lt;/h2&gt;

&lt;h3 id=&quot;创建一个lamp的项目&quot;&gt;创建一个LAMP的项目&lt;/h3&gt;

&lt;p&gt;首先是目录结构&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;├── README.md
├── apache
│   └── virtualhost.conf
├── docker-compose.yml
├── mysql
│   ├── Dockerfile
│   └── my.cnf
├── php
│   ├── Dockerfile
│   └── php.ini
└── src
    └── index.php
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;创建 docker-compose.yml&lt;/p&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;2'&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;mysql&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;mysql&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;3306:3306&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;password&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;MYSQL_DATABASE&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;phpdata&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;MYSQL_USER&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;user&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;MYSQL_PASSWORD&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;password&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;dbdata:/var/lib/mysql&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;php&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;./php&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;8080:80'&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;./src:/var/www/html&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;./apache:/etc/apache2/sites-enabled/&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;depends_on&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;mysql&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;phpmyadmin&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;phpmyadmin/phpmyadmin&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;8081:80'&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;links&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;mysql:db&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;PMA_USER&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;root&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;PMA_PASSWORD&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;password&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;adminsessions:/sessions&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;depends_on&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;mysql&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;php&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;dbdata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;adminsessions&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;问题记录&quot;&gt;问题记录&lt;/h2&gt;

&lt;h3 id=&quot;mysql-挂载-volume-后启动时显示无权限&quot;&gt;Mysql 挂载 volume 后启动时显示无权限&lt;/h3&gt;

&lt;p&gt;设置mysql的启动模式 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;privileged:true&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;另外这个问题一般不会发生，我之前遇到主要原因是我把多个 volume 都映射到了一个上面，导致目录内部读写发生冲突。&lt;/p&gt;

</description>
        <pubDate>Tue, 21 Feb 2017 00:00:00 +0000</pubDate>
        <link>http://cocoakc.com/2017/02/21/docker-summary.html</link>
        <guid isPermaLink="true">http://cocoakc.com/2017/02/21/docker-summary.html</guid>
        
        <category>Docker</category>
        
        
        <category>工具</category>
        
      </item>
    
      <item>
        <title>React 学习 - 开发环境搭建</title>
        <description>&lt;h2 id=&quot;1-安装-yarn&quot;&gt;1. 安装 Yarn&lt;/h2&gt;

&lt;p&gt;包管理可以用 npm 或者 yarn，好多人推荐 yarn，我这里就用这个了&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;brew update
brew install yarn
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;2-初始化项目文件夹&quot;&gt;2. 初始化项目文件夹&lt;/h2&gt;

&lt;p&gt;首先要做的是创建一个工程目录，然后在目录中执行 yarn 初始化即可&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;yarn init
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;3-安装-webpack&quot;&gt;3. 安装 Webpack&lt;/h2&gt;

&lt;p&gt;Webpack 可以让整个开发过程及其方便，这里只讲如何使用它来搭建 React 开发环境&lt;/p&gt;

&lt;p&gt;安装webpack&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;yarn add webpack webpack-dev-server path
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;创建 webpack 配置文件&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;touch webpack.config.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;写入以下内容&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Html webpack plugin setting&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;HtmlWebpackPlugin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;html-webpack-plugin&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;HtmlWebpackPluginConfig&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;HtmlWebpackPlugin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;./client/index.html&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;index.html&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;inject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Open browser plugin setting&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;OpenBrowserPlugin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;open-browser-webpack-plugin&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;./client/index.js&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;dist&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;index_bundle.js&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;loaders&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\.&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;js$/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;loader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;babel-loader&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;exclude&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/node_modules/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\.&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;jsx$/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;loader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;babel-loader&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;exclude&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/node_modules/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\.&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;css$/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;loader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;style-loader!css-loader&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;exclude&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/node_modules/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;plugins&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;HtmlWebpackPluginConfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;OpenBrowserPlugin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;http://localhost:8080&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这里需要说明一下：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;entry: 整个项目的入口文件&lt;/li&gt;
  &lt;li&gt;output: 编译好的文件输出位置&lt;/li&gt;
  &lt;li&gt;loaders: 用来告诉loaders处理哪些文件&lt;/li&gt;
  &lt;li&gt;plugins: 启用的webpack插件&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;html-webpack-plugin&quot;&gt;html-webpack-plugin&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;yarn add html-webpack-plugin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;上面我设置了 html 插件用来帮助把编译后的文件添加到body最后面，所以bundle.js这个js不需要我自己来添加到index.html中了&lt;/p&gt;

&lt;h3 id=&quot;css-loader-和-style-loader&quot;&gt;css-loader 和 style-loader&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;yarn add css-loader style-loader
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后在webpack.config.js中就可以使用 css-loader 和 style-loader 了&lt;/p&gt;

&lt;p&gt;之后我们在需要使用css的时候，直接用以下方式即可&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import &quot;./App.css&quot;;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;另外在写 react 应用时，也可以直接使用内敛样式，例如&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;React&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;react&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;style&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;backgroundColor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;#EEE&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;React&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;h1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Hello&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;world&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/h1&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;
&lt;/span&gt;      &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/div&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;
&lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;open-browser-webpack-plugin&quot;&gt;open-browser-webpack-plugin&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;yarn add open-browser-webpack-plugin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这个插件的作用是编译完成以后，打开浏览器&lt;/p&gt;

&lt;h2 id=&quot;设置-babel&quot;&gt;设置 Babel&lt;/h2&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;yarn add babel-loader babel-core babel-preset-es2015 babel-preset-react --dev
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;preset 是 babel 的插件，用来让 babel 帮忙转译。然后再创建一个 babel 配置文件&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;touch .babelrc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;写入内容&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;presets&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;es2015&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;react&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;4-设置-react-环境&quot;&gt;4. 设置 React 环境&lt;/h2&gt;

&lt;p&gt;安装 React&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;yarn add react react-dom
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;当前目录是这个样子&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;.
├── .babelrc
├── node_modules
├── package.json
├── webpack.config.js
└── yarn.lock
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;接下来我们加入 React 需要的文件&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;.
├── client
│   ├── components
│   │   └── App.js
│   ├── index.html
│   └── index.js
├── package.json
├── webpack.config.js
└── yarn.lock
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在 index.html 中写入&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;charset=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;utf-8&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;title&amp;gt;&lt;/span&gt;React App Setup&lt;span class=&quot;nt&quot;&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;root&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在 index.js 中写入&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;React&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;react&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ReactDOM&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;react-dom&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;App&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;./components/App.js&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Router&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Route&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;hashHistory&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;react-router&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;ReactDOM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Router&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;history&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hashHistory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Route&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;component&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;
&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Route&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/about&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;component&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;
&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/Router&amp;gt;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;,
&lt;/span&gt;  &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在 App.js 中写入&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;React&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;react&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;App&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;React&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Component&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
     &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;h1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Hello&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;World&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/h1&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;
&lt;/span&gt;      &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/div&amp;gt;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;;
&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;5-设置-react-router&quot;&gt;5. 设置 React-Router&lt;/h2&gt;

&lt;p&gt;想要完成页面跳转以及一些复杂的多页面操作，可以使用 React-Router 来支持&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;yarn add react-router
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;使用例子可以看上面index.js内容&lt;/p&gt;

&lt;h2 id=&quot;6-启动-react&quot;&gt;6. 启动 React&lt;/h2&gt;

&lt;p&gt;修改package.json，加入scripts&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;&quot;scripts&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;start&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;webpack-dev-server&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;build&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;webpack --progress --colors&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;build 方法会把网站打包一下，然后放到之前定义好的目录里面。start 可以直接开启开发模式，并且开启预览&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;yarn start
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;7-start-kit&quot;&gt;7. start kit&lt;/h2&gt;

&lt;p&gt;这些配置不需要每次都跑一次，我自己的放在 &lt;a href=&quot;https://github.com/suyan/react-start-kit&quot;&gt;Github&lt;/a&gt; 上。下载下来运行&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;yarn install
yarn start
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;即可开启一个 Web App 的开发了&lt;/p&gt;

&lt;h2 id=&quot;refer&quot;&gt;Refer&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://scotch.io/tutorials/setup-a-react-environment-using-webpack-and-babel&quot;&gt;Setup a React Environment Using webpack and Babel&lt;/a&gt;&lt;/p&gt;

</description>
        <pubDate>Sun, 19 Feb 2017 00:00:00 +0000</pubDate>
        <link>http://cocoakc.com/2017/02/19/setup-react-environment.html</link>
        <guid isPermaLink="true">http://cocoakc.com/2017/02/19/setup-react-environment.html</guid>
        
        <category>React</category>
        
        
        <category>技术</category>
        
      </item>
    
      <item>
        <title>在 Mac 下用 Docker 安装测试 HHVM</title>
        <description>&lt;p&gt;本来在 Mac 下用 Homebrew 安装 HHVM 应该是最容易的，但是最近有&lt;a href=&quot;https://github.com/hhvm/homebrew-hhvm/issues/68&quot;&gt;一个 bug&lt;/a&gt; 导致我在自己电脑上一直安装失败，所以我只好决定用 Docker 来装。&lt;/p&gt;

&lt;h2 id=&quot;安装-docker&quot;&gt;安装 Docker&lt;/h2&gt;

&lt;p&gt;现在在 Mac 下安装 Docker 非常方便，到 &lt;a href=&quot;https://docs.docker.com/docker-for-mac/&quot;&gt;官网&lt;/a&gt; 下载一个 dmg 包直接安装就好。&lt;/p&gt;

&lt;h2 id=&quot;制作-hhvm-镜像&quot;&gt;制作 HHVM 镜像&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/hhvm/hhvm-docker&quot;&gt;HHVM&lt;/a&gt; 官方提供了 Docker image，但是我在直接启动启动时发现官方的 image 竟然没有启动 hh_client ，所以需要自己稍微修改一下。&lt;/p&gt;

&lt;p&gt;另外在 build 过程中可能因为网络问题会失败… 因为你懂得的原因。所以直接把这个过程放在国外服务器上执行吧，速度快还不会出问题。&lt;/p&gt;

&lt;h3 id=&quot;下载-dockerfile&quot;&gt;下载 Dockerfile&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone https://github.com/hhvm/hhvm-docker.git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;官方给了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hhvm-latest-proxygen&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hhvm-latest&lt;/code&gt; 的 Dockerfile，这里我推荐前者，直接就可以映射一个代码目录，在浏览器测试 HHVM。后者的话需要登陆到 container 里面测试代码，不是非常方便。&lt;/p&gt;

&lt;h3 id=&quot;修改-dockerfile&quot;&gt;修改 Dockerfile&lt;/h3&gt;

&lt;p&gt;因为运行 HHVM 需要启动 typechecker，所以需要稍微修改一下 HHVM server 的启动命令。在刚刚下载好的目录 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hhvm-latest-proxygen&lt;/code&gt; 中代码的最后一行改为:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;CMD &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/usr/bin/hhvm&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;-m&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;server&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;-c&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;/etc/hhvm/server.ini&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;-c&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;/etc/hhvm/site.ini&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;-d&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;hhvm.hack.lang.look_for_typechecker=0&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;生成自己的-image&quot;&gt;生成自己的 image&lt;/h3&gt;

&lt;p&gt;然后在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hhvm-latest-proxygen&lt;/code&gt; 目录下执行下面命令即可：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker build &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; yourname/hhvm-proxygen &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;上传到到自己仓库中&quot;&gt;上传到到自己仓库中&lt;/h2&gt;

&lt;p&gt;我就直接上传到 &lt;a href=&quot;http://hub.docker.com&quot;&gt;Docker Hub&lt;/a&gt; 了。&lt;/p&gt;

&lt;p&gt;先用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker login&lt;/code&gt; 登陆一下，然后执行下面命令就行了&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker push yourname/hhvm-proxygen
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;启动-hhvm&quot;&gt;启动 HHVM&lt;/h2&gt;

&lt;p&gt;启动的话我建议弄一个自己的工作目录，建立一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;index.php&lt;/code&gt; 文件，写入以下内容&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hh&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;phpinfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后在工作目录下执行以下命令就可以了。&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker run &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;hhvm &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;pwd&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;:/var/www/public &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; 80:80 yourname/hhvm-proxygen
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;我绑定了80端口，所以直接打开 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://localhost&lt;/code&gt; 就可以测试了。想看 log 的话可以执行&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker logs hhvm
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
        <pubDate>Sat, 14 Jan 2017 00:00:00 +0000</pubDate>
        <link>http://cocoakc.com/2017/01/14/install-hhvm-on-mac-with-docker.html</link>
        <guid isPermaLink="true">http://cocoakc.com/2017/01/14/install-hhvm-on-mac-with-docker.html</guid>
        
        <category>Mac</category>
        
        <category>Docker</category>
        
        
        <category>工具</category>
        
      </item>
    
      <item>
        <title>在 Ubuntu 下部署 Shadowsocks</title>
        <description>&lt;p&gt;回国以后先试了部署 L2TP VPN（&lt;a href=&quot;/2016/12/30/deploy-l2tp-on-ubuntu.html&quot;&gt;在 Ubuntu 下部署 L2TP VPN&lt;/a&gt;），结果发现 VPN 稳定性还是略差，经常掉线。其实对于一般的浏览网页需求，Shadowsocks 就足够了，所以就有了此文。&lt;/p&gt;

&lt;h2 id=&quot;服务端&quot;&gt;服务端&lt;/h2&gt;

&lt;p&gt;我的环境是 Linode Tokyo + Ubuntu 14.04&lt;/p&gt;

&lt;p&gt;这里依然提供一个一键脚本，&lt;a href=&quot;https://teddysun.com/342.html&quot;&gt;Shadowsocks Python版一键安装脚本&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;想手动配置的往下看。&lt;/p&gt;

&lt;h3 id=&quot;安装-shadowsocks&quot;&gt;安装 Shadowsocks&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;apt-get update
apt-get &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;python-pip
pip &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;shadowsocks
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;配置-shadowsocks&quot;&gt;配置 Shadowsocks&lt;/h3&gt;

&lt;p&gt;下面的password那儿自己修改一下&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;MYIP&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;/sbin/ifconfig &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt;|grep inet|grep &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; 127.0.0.1|grep &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; inet6|awk &lt;span class=&quot;s1&quot;&gt;'{print $2}'&lt;/span&gt;|tr &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;addr:&quot;&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;/etc/shadowsocks.json&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;EOF&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;
{
    &quot;server&quot;:&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$MYIP&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;,
    &quot;server_port&quot;:8989,
    &quot;local_address&quot;: &quot;127.0.0.1&quot;,
    &quot;local_port&quot;:1080,
    &quot;password&quot;:&quot;test&quot;,
    &quot;timeout&quot;:300,
    &quot;method&quot;:&quot;aes-256-cfb&quot;,
    &quot;fast_open&quot;: false
}
&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;启动-shadowsocks&quot;&gt;启动 Shadowsocks&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ssserver &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; /etc/shadowsocks.json &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; start
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;客户端&quot;&gt;客户端&lt;/h2&gt;

&lt;p&gt;客户端的话可以直接去&lt;a href=&quot;https://shadowsocks.org/en/download/clients.html&quot;&gt;官网查看&lt;/a&gt;，我之前使用的是 &lt;a href=&quot;https://github.com/shadowsocks/ShadowsocksX-NG/releases&quot;&gt;ShadowsocksX-NG&lt;/a&gt;，但是我发现这里我自己设置了代理网站后总是不能立刻生效。&lt;/p&gt;

&lt;p&gt;所以现在改到了&lt;a href=&quot;https://github.com/zhuhaow/SpechtLite&quot;&gt;SpechtLite&lt;/a&gt;，根据&lt;a href=&quot;http://www.jianshu.com/p/663a898aa01a&quot;&gt;这篇文章&lt;/a&gt;可以非常方便配置。iOS下的客户端的话，推荐 &lt;a href=&quot;https://itunes.apple.com/cn/app/wingy-proxy-for-http-s-socks5/id1178584911?mt=8&quot;&gt;Wingy&lt;/a&gt;，设置也非常简单。&lt;/p&gt;

&lt;p&gt;这里提一下最近很火的 Surge，这个软件确实是神器一枚，使用起来非常方便。只是它暂时功能还有限，感觉并不值当前的价格，如果未来提供像 Charles 一样强大的功能的话，即使不用来科学上网，也是很值得入手的应用之一。不过据说还在开发中，所以之后可以考虑入手一枚。&lt;/p&gt;

</description>
        <pubDate>Sat, 31 Dec 2016 00:00:00 +0000</pubDate>
        <link>http://cocoakc.com/2016/12/31/deploy-shadowsocks-on-ubuntu.html</link>
        <guid isPermaLink="true">http://cocoakc.com/2016/12/31/deploy-shadowsocks-on-ubuntu.html</guid>
        
        <category>Tools</category>
        
        
        <category>工具</category>
        
      </item>
    
  </channel>
</rss>
