About neohope

一直在努力,还没想过要放弃...

Docker原理01

首先聊一下虚拟化技术。

虚拟化离我们很近,平时我们接触的虚拟化技术种类很多,比如硬件虚拟化(超线程技术),虚拟设备(虚拟光驱、虚拟软件、WinMount)、虚拟网络(VPN),桌面虚拟化(虚拟桌面、远程桌面),虚拟内存(利用交换文件或交换分区扩展系统可用内存),存储虚拟化(硬盘分区,网络硬盘映射),各类游戏机模拟器等。有些技术用的是如此普遍,你并不一定觉得它应该归类到虚拟化技术之中。但是,一旦提到虚拟化技术,你一定会想到其中一个,那就是虚拟机。

虚拟机技术按实现方式,分为纯硬件虚拟化、纯软件虚拟化及基于硬件辅助的软件虚拟化。其中纯硬件虚拟化,一般在大型机上实现的比较多,操作系统比较单一(其实支持该硬件架构的操作系统就可以,但多数情况下同一型号大型机操作系统的确比较单一),硬件架构复杂。纯软件虚拟化,其实现技术比较复杂,一般通过hypervisor提供硬件虚拟层,支持多种操作系统。时至今日,很多设备都提供了硬件辅助虚拟化的功能,这大大降低了虚拟机管理软件的实现难度,并增强了虚拟机的执行效率,所以现在一般的虚拟化软件都支持基于硬件辅助的软件虚拟化。

虚拟机技术按虚拟化程度分为三种,第一种是完全虚拟化,第二种准虚拟化,第三种是操作系统级层虚拟化。其中,
完全虚拟化,直接用软件/硬件辅助方式,不修改Guest,模拟虚拟机的全部硬件的技术,一般支持多种操作系统,但效率一般不高;
准虚拟化,直接用软件/硬件辅助方式,并同时通过修改Guest,对其进行一定程度的“欺骗”,实现与hypervisor相配合,实现虚拟化的技术,一般支持多种操作系统,运行效率比较高;
操作系统层虚拟化,是利用操作系统特性,利用一个操作系统内核,模拟多台虚拟设备的方式,由于一般需要共享操作系统内核,一般只支持一类操作系统;

还有一类特殊的虚拟机软件,叫跨平台虚拟化,允许针对特定CPU或者操作系统的软件,不做修改就能运行在其他平台上。如Wine(在Linux上模拟Windows应用),还有我们用的各类游戏模拟器(在Windows/Linux上模拟红白机FC、Projetc64、PSP)等。

那我们回过头来看下Docker的虚拟化方式与普通虚拟化方式的区别:
A、Dcoker虚拟化
Dcoker虚拟化
B、VMware VirtualBox虚拟化
VMware VirtualBox虚拟化

比较下来就很清楚了:

项目 Docker VMware VirtualBox
虚拟化技术 纯软件虚拟化 纯软件虚拟化+基于硬件辅助的软件虚拟化
虚拟化程度 操作系统级层虚拟化 完全虚拟化+准虚拟化
硬件抽象层 不需要 hypervisor
运行效率 安装插件前,效率较低;安装插件后,效率较高
支持系统 Linxu各发行版 硬件架构支持即可安装
需要安装Guest系统 共享内核,应用软件需要安装 完全安装

Docker建立自己的image

1、首先到dockerhub注册自己的账号
dockerhub

2、新建一个repository名字为justatest

3、取回debian6的镜像

docker pull debian:6

4、新建~/Docker/justatest/Dockerfile

From debian:6
RUN apt-get -y update && apt-get install -y fortunes
CMD /usr/games/fortune -a

5、创建并上传你的image

#创建image
docker build -t justatest .
#运行image
docker run justatest
#查看你的image id
docker images
#进行标记
docker tag image-id neohope/justatest:latest
#登录
docker login
#上传
docker push neohope/justatest
#下载
docker pull neohope/justatest
#运行
docker run neohope/justatest

安装Docker

按官方说法,Docker客户端现在可以安装到Linxu、Windows和MacOS上。但其实,在Windows和MacOS上,都需要安装一个工具叫做Docker Toolbox。该工具的作用是,帮你安装VirtualBox,创建虚拟机,并用Boot2Docker进行启动。

说实话,该工具做的还不是很完善,而且做了太多的假设,我并不喜欢。比如虚拟机路径必须在~/.docker/machine下面。比如会强制帮你安装网卡。比如docker-machine获取虚拟机的IP时,默认虚拟机第二块网卡设置为Host-Only,并通过VBoxManage获取虚拟机第二块网卡IP地址(源码中写死的)。不推荐大家使用。如果一定要用的话,大家还是不要用docker-machine,只需要docker和Git就够了。

说这么多,就是不想大家花费太多时间,用不完善的工具,来体验Docker的强大 。所以建议大家还是直接使用Linux,或者在虚拟机里自己安装Linux会好一些。我喜欢Debian,但如果你不太熟,建议用Ubuntu。

1、安装Linux,并保证可以联网

2、安装Docker

#从网址取回文件,输出到标准输出,并传递给sh执行
wget -qO- https://get.docker.com/ | sh

3、测试安装是否成功

#docker从repository取回hello-world:latest的镜像,并运行
docker run hello-world

#docker从repository取回debian:latest的镜像,并运行bash命令
docker run -it debian bash

4、docker常用命令

#查看本地有哪些镜像
docker images

#查找debian镜像
docker search debian

#取回debian6的镜像
docker pull debian:6

#按image-id删除镜像
docker rmi image-id

#查看当前运行的容器
docker ps

#kill一个容器
docker kill contianer-id

#删掉一个容器 
docker rm contianer-id

#杀掉所有容器
docker kill $(docker ps -a -q)

#删除所有容器
docker rm $(docker ps -a -q)

PS:
boot2docker的默认用户为docker,密码为tcuser

Docker开启Remote API

远程执行Docker命令,基本有两种方式,一种是SSH到宿主机上,相当于在宿主机本地执行。一种是利用Docker的Remote API,打开2375端口,直接远程执行。本文说的是第二种方式,发行版Debian8。

1、临时方案:在宿主机上直接执行

#旧版本
docker -H 0.0.0.0:2375 -d &
#新版本
docker daemon -H 0.0.0.0:2375 &

2、永久方式
2.1编辑/etc/systemd/system/docker-tcp.socket

[Unit]
Description=Docker Socket for the API

[Socket]
ListenStream=2375
BindIPv6Only=both
Service=docker.service

[Install]
WantedBy=sockets.target

2.2执行

systemctl enable docker-tcp.socket
systemctl stop docker
systemctl start docker-tcp.socket
systemctl start docker

3、测试

#本地
docker -H tcp://127.0.0.1:2375 ps
#远程
docker -H tcp://HOST_IP:2375 ps

Docker常用命令

1、镜像相关的命令

#从docker hub查询镜像
sudo docker search xxx

#从docker hub拉取镜像
sudo docker pull xxx

#列出本地镜像
sudo docker images

#删除本地镜像
sudo docker rmi xxx

#登陆登出registry
sudo docker login
sudo docker logout

#从docker file创建镜像
sudo docker build

#从contianer创建镜像
sudo docker commit

#标记镜像
sudo docker tag

#镜像发送到registry
sudo docker push

2、contianer相关命令

#创建但不运行contianer
sudo docker create xxx

#创建并运行contianer
sudo docker run xxx

#运行contianer
sudo docker start xxx

#停止contianer
sudo docker stop xxx

#杀死contianer
sudo docker kill xxx

#查看正在运行的本地contianer列表
sudo docker ps

#查看全部本地contianer列表
sudo docker ps -a

#查看contianer详情
sudo docker inspect xxx

#查看contianer日志
sudo docker logs xxx

#查看contianer端口
sudo docker port xxx

#查看contianer进程
sudo docker top xxx

#删除contianer
sudo docker rm xxx

3、宿主机操与虚拟机互操作

#附加到contianer,没有反应,可以按向上键
sudo docker attach xxx
#退出
#Ctrl+D
#detach
#Ctrl+P Ctrl+Q

#容器与宿主机之间拷贝文件
sudo docker cp xxx:/yyy /zzz

#在宿主机执行容器中的命令
sudo docker exec xxx yyy

#查看docker信息
sudo docker info

4、网络

#查看网络
sudo docker network ls

#创建网络
sudo docker network create xxx

CMD常用命令17常用软件注册为Widows服务

1、Apache注册为Widows服务

httpd -k install

2、MySQL注册为Widows服务

mysqld --install MySQL --defaults-file="D:\MySQL\MySQL Server 5.1\my.ini"

3、PostgreSQL注册为Widows服务

pg_ctl.exe register -N "postgresql-8.4" -D "D:/PostgreSQL/8.4/data" -w

4、SVN注册为Widows服务

sc create svnserve binPath= "\"D:\Subversion\bin\svnserve.exe\" --service -r \"D:\Subversion\repository\"" displayname= "Subversion Service" depend= Tcpip start= auto 
sc start svnserve 
sc stop svnserve 
sc delete svnserve

5、redis注册为Widows服务

#loglevel 分为debug, notice, warning三级
redis-server.exe --service-install D:\Database\Redis2.8\db\redis.windows.conf --loglevel notice
redis-server --service-start
redis-server --service-stop
redis-server --service-uninstall

6、mongodb注册为Widows服务

mongod --dbpath=D:\Database\MongoDB3\db --logpath=D:\Database\MongoDB3\log\mongo.log --port 27027 --noauth --install -serviceName MongoDB01 --serviceDisplayName MongoDB01 
net start MongoDB01

FreeBSD10安装开发环境

1、安装JDK
1.1、Oracle没有为FreeBSD提供JDK环境,自带版本也挺高,那就安装默认的咯

pkg install jdk8

*在windows下编译过,超级大,时间也很久,实在不想编译openjdk了。

1.2、修改/etc/fstab文件,增加下面两行,搞定

# Device	Mountpoint	FStype	Options	Dump	Pass#
/dev/ada0p2	/		ufs	rw	1	1
/dev/ada0p3	none		swap	sw	0	0
fdesc		/dev/fd		fdescfs	rw	0	0
proc		/proc		procfs	rw	0	0

2、自己编译Ruby,当然也可以用pkg安装
2.1、下载并编译源码
ruby-lang.org

./configure --prefix=usr/ruby/ruby_2.2.3
make
make install

2.2、配置环境变量,默认为csh
编辑~/.cshrc

set RUBY_HOME=/usr/ruby/ruby_2.2.3
set path=($RUBY_HOME/bin $path)

重新登录一下。

2.3、切换为国内源

gem sources --add https://ruby.taobao.org/
gem sources --remove https://rubygems.org/
gem sources -l

2.4、安装gems

$ gem install rails
$ gem install redis

3、自己编译redis,当然也可以用pkg安装
3.1、下载并编译源码
redis.io

pkg install gmake
gmake
gmake PREFIX=/usr/redis/redis_3.0.4 install

3.2、配置环境变量,默认为csh
编辑~/.cshrc

set REDIS_HOME=/usr/redis/redis_3.0.4
set path=($REDIS_HOME/bin $path)

重新登录一下。

4、安装mongodb
4.1、下载并编译源码
mongodb.org

pkg install gcc
pkg install scons
pkg install python
pkg install libexecinfo

scons all
scons --prefix=/usr/mongodb/mongodb_3.0.7 install

*顺便说一下,这个编译后是18G,安装后为1.1G。。。
*如果你用的是3.0.7版本的源码,在FreeBSD下需要打补丁
github.com

4.2、配置环境变量,默认为csh
编辑~/.cshrc

set MONGODB_HOME=/usr/mongodb/mongodb_3.0.7
set path=($MONGODB_HOME/bin $path)

重新登录一下。

Virtualbox安装配置FreeBSD10

1、新建虚拟机,下载DVD镜像文件,安装虚拟机,整个过程比较简单:分区,选择需要的包,配置网络,配置用户
其中,我的虚拟机网卡配置为:
le0 是hostonly,用于与宿主机、其他虚拟机进行网络通许,要手工设置
le1 是nat,用于蹭网,设置为DHCP就好了

2、安装后重启,发现新用户不能su,将新用户添加到wheel组

#此命令一如既往的强大
bsdconfig

3、然后发现,le1发现可以连外网,但le0配置有些问题,编辑/etc/rc.conf

#network config
hostname="freebsd10"
ifconfig_le0="inet 172.16.172.5 netmask 255.255.0.0"
ifconfig_le1="DHCP"
ip6addrctl_enable="NO"
defaultrouter="10.0.3.2"
#static_routes="net1"
#route_net1="-net 172.16.172.0/16 172.16.172.1"

重启网络,OK。

4、找了一下,VirtualBox自带的扩展插件是没有BSD系统支持的,那就安装开源的呗
首先尝试了bsdconfig进行安装,但系统提示找不到数据库

bsdconfig
#选择Packages
no pkg(8) database found.

4.1A网上找了下,从DVD安装可以这样处理:

mount -t cd9660 /dev/cd0 /dist
env REPOS_DIR=/dist/packages/repos pkg search virtualbox
env REPOS_DIR=/dist/packages/repos pkg install virtualbox-ose-additions 

4.1B或者,直接采用网络安装可以这样处理:

pkg install virtualbox-ose-additions 

4.2安装后,需要在/etc/rc.conf中增加

vboxguest_enable=“YES”
vboxservice_enable=“YES”

重启

5、安装图形界面
从DVD安装可以这样处理:
5.1A

mount -t cd9660 /dev/cd0 /dist

env REPOS_DIR=/dist/packages/repos pkg search xorg
env REPOS_DIR=/dist/packages/repos pkg install xorg

env REPOS_DIR=/dist/packages/repos pkg search gnome
env REPOS_DIR=/dist/packages/repos pkg install gnome3

5.1B或者,直接采用网络安装可以这样处理:

pkg install xorg
pkg install gnome3

5.2A安装完毕后,如果想重启后直接进入图形界面,需要在/etc/rc.conf中增加

gdm_enable="YES"
gnome_enable="YES"

5.2B如果想重启后进入命令行界面,需要在/etc/rc.conf中增加

dbus_enable="YES"

然后,执行命令

echo exec gnome-session > ~/.xinitrc
startx

6、发现命令行界面分辨率太低
6.1查看系统支持的分辨率

#列出所有支持的分辨率
vidcontrol -i mode
#尝试1024x768x24
vidcontrol MODE_280

6.2在/etc/rc.conf中增加

allscreens_flags="MODE_280"

7、启动后,发现sendmail服务启动耗时很久,反正用不到,编辑/etc/rc.conf文件,禁用之

vi /etc/rc.conf
sendmail_enable="NONE"
sendmail_submit_enable="NO"
sendmail_outbound_enable="NO"
sendmail_msp_queue_enable="NO"

8、最终,我的/etc/rc.conf文件如下

#network config
hostname="freebsd10"
ifconfig_le0="inet 172.16.172.5 netmask 255.255.0.0"
ifconfig_le1="DHCP"
ip6addrctl_enable="NO"
defaultrouter="10.0.3.2"
#static_routes="net1"
#route_net1="-net 172.16.172.0/16 172.16.172.1"

#display config
vboxguest_enable="YES"
vboxservice_enable="YES"
allscreens_flags="MODE_280"
#gdm_enable="YES"
#gnome_enable="YES"

#other service config
sshd_enable="YES"
powerd_enable="YES"
moused_enable="YES"
dbus_enable="YES"

#"AUTO" to enable crash dumps, "NO" to disable crash dumps
dumpdev="AUTO"

#disapbled service
zfs_enable="NO"
sendmail_enable="NONE"
sendmail_outbound_enbale="NO"
sendmail_msp_queue_enable="NO"
sendmail_submit_enable="NO"

MongoDB副本集(Java)

还是蛮简单的,驱动把任务全部做掉了

package com.djhu.mongodb.test;

import java.util.Arrays;

import org.bson.Document;

import com.mongodb.MongoClient;
import com.mongodb.ServerAddress;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;

public class ReplTest
{
	private static void testInsert() 
	{
		MongoClient mongoClient = new MongoClient(Arrays.asList(
				   new ServerAddress("172.16.172.4", 27017),
				   new ServerAddress("172.16.172.4", 27018),
				   new ServerAddress("172.16.172.4", 27019)));

		MongoDatabase db = mongoClient.getDatabase("test");
		MongoCollection collection = db.getCollection("person");
		
		Document doc = new Document();
		doc.put("name", "tuzi");
		doc.put("age", 27);
		doc.put("sex", "Female");
		collection.insertOne(doc);
	}

	public static void main(String[] args)
	{
		testInsert();
	}
}

如果遇到下面的错误,是因为用了localhost作为replSet的地址,重新config一下就好了

Caused by: java.net.ConnectException: Connection refused: connect
	at java.net.PlainSocketImpl.socketConnect(Native Method)
	at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:333)
	at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:195)
	at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:182)
	at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366)
	at java.net.Socket.connect(Socket.java:519)
	at com.mongodb.connection.SocketStreamHelper.initialize(SocketStreamHelper.java:50)
	at com.mongodb.connection.SocketStream.open(SocketStream.java:58)
	... 3 more
Exception in thread "main" com.mongodb.MongoTimeoutException: Timed out after 30000 ms while waiting for a server that matches PrimaryServerSelector. Client view of cluster state is {type=REPLICA_SET, servers=[{address=localhost:27017, type=UNKNOWN, state=CONNECTING, exception={com.mongodb.MongoSocketOpenException: Exception opening socket}, caused by {java.net.ConnectException: Connection refused: connect}}, {address=localhost:27018, type=UNKNOWN, state=CONNECTING, exception={com.mongodb.MongoSocketOpenException: Exception opening socket}, caused by {java.net.ConnectException: Connection refused: connect}}, {address=localhost:27019, type=UNKNOWN, state=CONNECTING, exception={com.mongodb.MongoSocketOpenException: Exception opening socket}, caused by {java.net.ConnectException: Connection refused: connect}}, {address=localhost:27020, type=UNKNOWN, state=CONNECTING, exception={com.mongodb.MongoSocketOpenException: Exception opening socket}, caused by {java.net.ConnectException: Connection refused: connect}}]
	at com.mongodb.connection.BaseCluster.createTimeoutException(BaseCluster.java:370)
	at com.mongodb.connection.BaseCluster.selectServer(BaseCluster.java:101)
	at com.mongodb.binding.ClusterBinding$ClusterBindingConnectionSource.<init>(ClusterBinding.java:75)
	at com.mongodb.binding.ClusterBinding$ClusterBindingConnectionSource.<init>(ClusterBinding.java:71)
	at com.mongodb.binding.ClusterBinding.getWriteConnectionSource(ClusterBinding.java:68)
	at com.mongodb.operation.OperationHelper.withConnection(OperationHelper.java:175)
	at com.mongodb.operation.MixedBulkWriteOperation.execute(MixedBulkWriteOperation.java:141)
	at com.mongodb.operation.MixedBulkWriteOperation.execute(MixedBulkWriteOperation.java:72)
	at com.mongodb.Mongo.execute(Mongo.java:747)
	at com.mongodb.Mongo$2.execute(Mongo.java:730)
	at com.mongodb.MongoCollectionImpl.executeSingleWriteRequest(MongoCollectionImpl.java:482)
	at com.mongodb.MongoCollectionImpl.insertOne(MongoCollectionImpl.java:277)
	at com.djhu.mongodb.test.ReplTest.testInsert(ReplTest.java:28)
	at com.djhu.mongodb.test.ReplTest.main(ReplTest.java:33)