Gitlab重置用户密码

自建的Gitlab服务器在阿里云上,阿里云默认屏蔽了对外的25端口连接。每添加新用户,就会反馈重置密码的邮件收不到。解决方法是登录到服务器上用mailq命令找到邮件ID,接着用postcat命令找出链接发给对方完成密码重置工作。

这次的新用户比较奇怪(也可能是gitlab升级),使用postcat获取到的链接无效,无法重置密码。为了让其正常使用,先从管理员身份切换过去并添加SSH公钥。

事后为了解决这个问题,暂时想到两个办法:1. 使用海外的服务器;2. 使用465等SSL加密端口。第一个方法作为备选方案,优先考虑了第二种方案。遗憾的是按照官方文档配置,Gitlab不屈不挠的使用sendmail而非SMTP方式发送邮件。折腾了一个多小时还没弄好,有点心累。

快要放弃的时候转念一想,我需要的是重置密码功能,邮件先放一边吧!于是开始寻找重置用户密码方法,该过程可谓是轻松加愉快,很快就重置了用户的密码。

具体步骤如下:

# 进入gitlab控制台
gitlab-rails console
# 找出用户并重置密码
user = User.find_by(email: '[email protected]')
user.password='1234ABCD'
user.password_confirmation='1234ABCD'
user.save!
# 退出控制台
exit

输出内容示例如下:

[root@localhost gitlab]# gitlab-rails console
Loading production environment (Rails 4.2.8)
irb(main):001:0> user = User.find_by(email: '[email protected]')
=> #<User id:12 @foo>
irb(main):002:0> user.password='1234ABCD'
=> "1234ABCD"
irb(main):003:0> user.password_confirmation='1234ABCD'
=> "1234ABCD"
irb(main):004:0> user.save!
Enqueued ActionMailer::DeliveryJob (Job ID: ea0072d2-5cd5-4b6e-bdad-fa938d977e47) to Sidekiq(mailers) with arguments: "DeviseMailer", "password_change", "deliver_now", gid://gitlab/User/12
=> true

自动化部署之gitlab权限管理–issue管理

1、创建Group,User,Project

创建一个组,组名为java

Group path http://192.168.56.11/java
Visibility Level:    #为权限级别,一般使用Private
Private
Internal
Public

创建一个PM的用户作为项目管理者并加入到java组内

未分类

创建一个项目:

未分类

创建dev1和dev2的用户作为开发者,并加入到项目中

未分类

2、测试dev1,dev2拉取代码库

(1)生成ssh-key

[root@linux-node1 ~]# ssh-keygen 
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): 
Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:Hf3O9F7sS9N04cFUr3Awb/Wec28gTpHYyRZMCzLW9q0 root@linux-node1
The key's randomart image is:
+---[RSA 2048]----+
|        +..o=  .+|
|       . oo*.Oo.o|
|         .o.@.++o|
|         . o.*oo+|
|        S . o.=+=|
|           oE= =*|
|            . ooB|
|              .+o|
|               .+|
+----[SHA256]-----+
[root@linux-node1 ~]# cat .ssh/id_rsa.pub 
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDLDVIqTAvJtj8Uc+SvhcKOKuDtURt3YBxHo9enUkDjOWtSygLZI4hSrEsnvjHdnxeBGOgjPrxEfMMdNCno4pox7V/8bIU9LRVp2eeQFS+N+bSmbJlTKyODa0tabPwT7URYoiFI3giQamQdA0AwwPCPM/RcXwHJsw4q0O/2woCqNKq2tHaUFBqojd2KvqavzpB+4+AdKJSoabwLhE8dzfjIR/eHY31Y2C/+m9sU504v+R0GsAqr5uifi6Ct9eFvumI54BvHssIpZFZmADTT35b1aP0WSwZb2VEhXjaia8L6h/6ANn1NuHGgYZqNiYT6JILESKbrc7PyJOn9DfHKSMq9 root@linux-node1


(2)将公钥(id_rsa.pub)放进dev1账户中
在admin账户下给dev1,dev2账户设置密码,然后使用dev1登录gitlab,做如下操作添加ssh-key:
测试是否能正常拉取代码库app1

[root@linux-node1 ~]# git clone [email protected]:java/app1.git
Cloning into 'app1'...
The authenticity of host '192.168.56.11 (192.168.56.11)' can't be established.
ECDSA key fingerprint is SHA256:p2lhKmsPQ6K+dWHHvbJg0GV+Ni9VM7vlViKrYsZLP1s.
ECDSA key fingerprint is MD5:22:14:1c:37:de:47:1c:4a:2f:88:b1:dc:e2:d0:02:17.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.56.11' (ECDSA) to the list of known hosts.
warning: You appear to have cloned an empty repository.
Checking connectivity... done.
[root@linux-node1 ~]# ll
total 6804
-rw-------.  1 root root     948 Dec  3 01:21 anaconda-ks.cfg
drwxr-xr-x   3 root root      17 Dec 20 15:00 app1
drwxr-xr-x  22 root root   24576 Dec  8 22:16 git-2.7.4
drwxr-xr-x   3 root root      65 Dec  9 01:23 test
-rw-r--r--   1 root root 6918037 Dec  8 22:09 v2.7.4.zip
[root@linux-node1 ~]# cd app1
[root@linux-node1 app1]# ll
total 4
-rw-r--r-- 1 root root 19 Dec 20 15:05 readme

未分类

到此,Linux环境下完成了gitlab的授权管理代码库。

下面以PM用户进行创建开发计划
开发一个官网V1.0版本,包含首页和新闻

(1)创建里程碑(Milestone)

未分类

(2)依次把任务首页,新闻添加到里程碑,并进行任务分配给开发者

未分类

(3)使用dev1用户登录查看,会有任务提示,如图:

未分类

(4)dev1开发者收到任务,进行开发

[root@linux-node1 app1]# git checkout -b shouye    #创建首页分支
Switched to a new branch 'shouye'
[root@linux-node1 app1]# git status
On branch shouye
nothing to commit, working directory clean
[root@linux-node1 app1]# echo "<h1> welcome to www.123.com" > index.html    #进行开发
[root@linux-node1 app1]# ll
total 8
-rw-r--r-- 1 root root 28 Dec 20 15:50 index.html
-rw-r--r-- 1 root root 19 Dec 20 15:05 readme
[root@linux-node1 app1]# git add .
[root@linux-node1 app1]# git commit -m "shouye"    #开发完成,提交本地仓库
[shouye babdcb5] shouye
 1 file changed, 1 insertion(+)
 create mode 100644 index.html
[root@linux-node1 app1]# git push origin shouye    #提交到远程库
Counting objects: 3, done.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 292 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
remote: 
remote: To create a merge request for shouye, visit:
remote:   http://192.168.56.11/java/app1/merge_requests/new?merge_request%5Bsource_branch%5D=shouye
remote: 
To [email protected]:java/app1.git
 * [new branch]      shouye -> shouye

可以看到有刚才创建的分支,点击”merge request”合并分支请求,之后PM用户登录处理合并请求。此时,一个功能的开发流程就完成。

未分类

未分类

总结:

PM在gitlab创建任务,分配给开发人员
开发人员领取任务后,在本地使用git clone拉取代码库
开发人员创建开发分支(git checkout -b dev),并进行开发
开发人员完成之后,提交到本地仓库(git commit )
开发人员在gitlab界面上申请分支合并请求(Merge request)
PM在gitlab上查看提交和代码修改情况,确认无误后,确认将开发人员的分支合并到主分支(master)
开发人员在gitlab上Mark done确认开发完成,并关闭issue。这一步在提×××并请求时可以通过描述中填写”close #1″等字样,可以直接关闭issue。

用 Docker Compose 搭建 Rails 开发环境

Docker 是目前最热门的容器格式,Docker Compose 是用于管理包含多个 Docker 容器的应用的工具,借助 Docker 和 Docker Compose,我们可以轻松搭建可复现的开发环境。

这篇教程展示如何从零开始用 Docker Compose 搭建 Rails/PostgreSQL 开发环境。

本文主要参考了 Quickstart: Compose and Rails。但原文有一点问题,于是我加上自己的见解写成这篇博客。

安装 Docker

首先,需要在自己的开发机上安装 Docker,你可以在 https://www.docker.com/ 找到适合自己操作系统的 Docker 安装方式。

安装完毕后,可以在命令行中使用 docker 命令:

$ docker --version
Docker version 17.03.1-ce, build c6d412e

创建项目

创建项目目录:

$ mkdir myapp
$ cd myapp

接着,创建一个 Gemfile 文件,包含以下内容:

source 'https://rubygems.org'

gem 'rails', '5.1.0.rc2'

然后,创建一个空的 Gemfile.lock 文件:

$ touch Gemfile.lock

之所以这么做,是因为不希望在主机环境安装 Ruby 和其它依赖,而是都放到镜像中。这两个文件用于在镜像中安装 Rails。

接着,创建一个 Dockerfile 文件,该文件用于定义如何构建 Rails 镜像:

FROM ubuntu:16.04

RUN apt-get update && apt-get install -y curl apt-transport-https && 
  curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && 
  echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list

RUN apt-get update && apt-get install -y 
  build-essential 
  libpq-dev 
  nodejs 
  ruby 
  ruby-dev 
  tzdata 
  yarn 
  zlib1g-dev

WORKDIR /app

RUN gem install bundler
ADD Gemfile /app/Gemfile
ADD Gemfile.lock /app/Gemfile.lock
RUN bundle install
ADD . /app

这个 Dockerfile 基于 Ubuntu 16.04,安装了创建 Rails 项目所需要的基础包,并将项目目录设定在 /app。你可以阅读 https://docs.docker.com/ 学习怎么定制 Dockerfile。

然后,创建一个 docker-compose.yml 文件,该文件用于定义 docker-compose 如何启动应用:

version: '2'
services:
  web:
    build: .
    command: bundle exec rails s -p 3000 -b 0.0.0.0
    volumes:
      - .:/app
    ports:
      - 3000:3000
    depends_on:
      - db
  db:
    image: postgres

在这个文件里,我们定义了两个服务。web 服务用于运行 Rails,镜像将根据当前目录的 Dockerfile 构建;db 服务用于运行 PostgreSQL 进程,镜像使用 Docker 官方提供的 postgres。你可以在 https://docs.docker.com/compose/compose-file/ 找到其它配置的定义。

接下来,执行以下命令:

$ docker-compose run web rails new . --force --database=postgresql

该命令会在当前目录创建 Rails 项目:

$ ls -l
total 72
-rw-r--r--   1 rei  staff   522  4 25 22:59 Dockerfile
-rw-r--r--   1 rei  staff  1989  4 25 23:02 Gemfile
-rw-r--r--   1 rei  staff  4847  4 25 23:03 Gemfile.lock
-rw-r--r--   1 rei  staff   374  4 25 23:02 README.md
-rw-r--r--   1 rei  staff   227  4 25 23:02 Rakefile
drwxr-xr-x  10 rei  staff   340  4 25 23:02 app
drwxr-xr-x   9 rei  staff   306  4 25 23:03 bin
drwxr-xr-x  14 rei  staff   476  4 25 23:02 config
-rw-r--r--   1 rei  staff   130  4 25 23:02 config.ru
drwxr-xr-x   3 rei  staff   102  4 25 23:02 db
-rw-r--r--   1 rei  staff   206  4 25 22:59 docker-compose.yml
drwxr-xr-x   4 rei  staff   136  4 25 23:02 lib
drwxr-xr-x   3 rei  staff   102  4 25 23:02 log
-rw-r--r--   1 rei  staff    61  4 25 23:02 package.json
drwxr-xr-x   9 rei  staff   306  4 25 23:02 public
drwxr-xr-x  11 rei  staff   374  4 25 23:02 test
drwxr-xr-x   4 rei  staff   136  4 25 23:02 tmp
drwxr-xr-x   3 rei  staff   102  4 25 23:02 vendor

接着,重建 Docker 镜像:

$ docker-compose build

每当修改了 Dockerfile,你都需要重建镜像。如果修改了 Gemfile,还需要先在容器内运行 bundle,然后重建镜像:

$ docker-compose run web bundle
$ docker-compose build

连接数据库

现在我们已经可以让 Rails 跑起来,但还需要修改一些配置让 Rails 连上数据库。默认情况下,Rails 的 development 和 test 环境会连接 localhost 主机上的数据库,根据之前的 docker-compose.yml 配置,我们需要将数据库的主机名改为 db。另外,还需要修改 username 以适配 postgres 镜像的默认配置。修改后的 database.yml 配置如下:

development:
  <<: *default
  database: app_development
  host: db
  username: postgres

test:
  <<: *default
  database: app_test
  host: db
  username: postgres

现在可以启动 Rails 进程了:

$ docker-compose up

如果一切正常,你会看到一些 postgres 的日志,然后是 Rails 启动日志:

web_1  | => Booting Puma
web_1  | => Rails 5.1.0.rc2 application starting in development on http://0.0.0.0:3000
web_1  | => Run `rails server -h` for more startup options
web_1  | Puma starting in single mode...
web_1  | * Version 3.8.2 (ruby 2.3.1-p112), codename: Sassy Salamander
web_1  | * Min threads: 5, max threads: 5
web_1  | * Environment: development
web_1  | * Listening on tcp://0.0.0.0:3000
web_1  | Use Ctrl-C to stop

如果你需要运行数据库迁移,可以打开另一个终端运行:

$ docker-compose run web rails db:create
$ docker-compose run web rails db:migrate

TIP: 以后运行 rails 命令,都需要在前面加上 docker-compose run web。

用浏览器访问 http://localhost:3000 ,你会看到 Rails 的欢迎信息:

未分类

将 Dockerfile docker-compose.yml 与项目文件一并提交到版本控制里,这样新开发者参与项目的时候就可以用 docker-compose up 一键启动开发环境。

mint 18.2(Sonya)安装docker

与ubuntu安装大体一致,参考官网提供的ubuntu安装方式
官方安装 https://docs.docker.com/engine/installation/linux/docker-ce/ubuntu/

安装步骤

1、删除原有版本

sudo apt-get remove docker docker-engine docker.io

2、(推荐略过这一步) 现在docker默认的文件系统为overlay2,如果需要使用aufs(早期docker的文件系统),请执行以下命令

sudo apt-get update
sudo apt-get install 
    linux-image-extra-$(uname -r) 
    linux-image-extra-virtual

3、安装docker ce

docker-ce 是docker的社区版,免费使用,有三种方式安装

  • 添加源,使用apt-get安装
  • 下载deb包,使用dpkg安装
  • 使用提供的脚本安装
    这里选择第一种安装方式

使用apt-get安装

安装需要的工具,

sudo apt-get update
sudo apt-get install 
    apt-transport-https 
    ca-certificates 
    curl 
    software-properties-common

添加认证,

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

根据你的硬件架构选择相应的源进行添加,测试机器为amd64架构,docker支持amd64,armhf,s390x等方式,其余架构添加方式参考官网
下面命令中$(lsb_release -cs)查看系统codename,mint基于ubuntu,使用ubuntu的软件源 ,
所以将

sudo add-apt-repository 
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu 
   $(lsb_release -cs) 
   stable"

替换为 xenial ,执行以下替代命令

sudo add-apt-repository 
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu 
   xenial 
   stable"

更新软件源

sudo apt-get update

测试环境直接安装最新版docker-ce

sudo apt-get install docker-ce

如果是正式环境,可能需要安装指定版本的

sudo apt-get install docker-ce=<VERSION>

如果没有报错,那就大功告成~
跑个hello world

sudo docker run hello-world
Unable to find image ‘hello-world:latest’ locally 
latest: Pulling from library/hello-world 
9a0669468bf7: Pull complete

说明已经获取到官方仓库里的镜像啦~

权限问题

因为安装都是使用sudo即root权限安装,使用的时候,如果没有root权限会提示

Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: 巴拉巴拉

/var/run/docker.sock 作用

它是Docker守护进程(Docker daemon)默认监听的Unix域套接字(Unix domain socket),容器中的进程可以通过它与Docker守护进程进行通信 .
把自己加到docker组

sudo usermod -a -G docker $(whoami)

完全退出当前登录用户,使修改生效

安装docker-compose

docker-compose 是个官方提供管理镜像的工具,对镜像进行一些编排,减化docker使用命令等功能  
官方安装:https://docs.docker.com/compose/install/

下载二进制包,可以直接从github获取,参考下面命令,
其中1.18.0 是截止到文章发布日期的最新版本,具体版本后,点击链接查询

sudo curl -L https://github.com/docker/compose/releases/download/1.18.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose

添加执行权限

sudo chmod +x /usr/local/bin/docker-compose

大功告成

docker-compose --version
# docker-compose version 1.18.0, build 8dd22a9

.NET Core容器化之多容器应用部署@Docker-Compose

未分类

1. 引言

紧接上篇.NET Core容器化@Docker,这一节我们先来介绍如何使用Nginx来完成.NET Core应用的反向代理,然后再介绍多容器应用的部署问题。

2. Why Need Nginx

.NET Core中默认的Web Server为Kestrel。

Kestrel is great for serving dynamic content from ASP.NET, however the web serving parts aren’t as feature rich as full-featured servers like IIS, Apache or Nginx. A reverse proxy-server can allow you to offload work like serving static content, caching requests, compressing requests, and SSL termination from the HTTP server.

Kestrel可以很好的用来为ASP.NET提供动态内容,然而在Web服务方面没有IIS、Apache、Nginx这些全功能的服务器完善。我们可以借助一个反向代理服务器接收来自互联网的HTTP请求并在经过一些初步处理(比如请求的缓存和压缩、提供静态内容、SSL Termination)后将其转发给Kestrel。

未分类

未分类

借助反向代理服务器(本文使用Nginx),不仅可以给我们的Web网站提供了一个可选的附加层配置和防御,而且可以简化负载均衡和SSL设置。而更重要的是,反向代理服务器可以很好的与现有的基础设施进行整合。

3. Hello Nginx

同样我们还是基于Docker来试玩一下Nginx。

//拉取Nginx镜像
$ docker pull nginx
//启动Nginx容器
$ docker run -d -p 8080:80 --name hellonginx nginx

上面我们以后台运行的方式启动了一个命名为hellonginx的nginx容器,其端口映射到宿主机的8080端口,我们现在可以通过浏览器直接访问http://:8080即可看到nginx的欢迎界面。

未分类

至此,一个Nginx容器就启动完毕了。那如何进行反向代理呢?别急,我们一步一步来。

4. 反向代理.NET Core MVC

4.1. 启动Web容器

还记得我们上一篇本地打包MVC项目创建的hellodocker.web的镜像吗?这里我们再启动该镜像创建一个容器:

//启动一个helodocker.web的镜像并命名容器为hellodocker.web.nginx
#  docker run -d -p 5000:5000 --name hellodocker.web.nginx hellodocker.web
160166b3556358502a366d1002567972e242f0c8be3a751da0a525f86c124933
//尝试访问刚刚运行的容器
[root@iZ288a3qazlZ ~]# curl -I http://localhost:5000
HTTP/1.1 200 OK
Date: Sun, 24 Dec 2017 02:48:16 GMT
Content-Type: text/html; charset=utf-8
Server: Kestrel
Transfer-Encoding: chunked

OK,我们开放了宿主机的5000端口用来映射我们启动的MVC容器。

4.2. 配置反向代理

下面我们就来配置Nginx来反向代理我们刚启动的Web容器。
要想Nginx成功代理指定的容器内运行的Web网站,首先我们得知道容器对应的IPAddress。使用docker inspect 即可查到。

//查看正在运行的容器列表
$ docker ps 
CONTAINER ID        IMAGE                          COMMAND                  CREATED             STATUS              PORTS                            NAMES
d046b7b878a0        hellodocker.web                "dotnet run"             5 seconds ago       Up 3 seconds        0.0.0.0:5000->5000/tcp           hellodocker.web.nginx

//使用`|`管道操作符加上`grep`过滤操作符可以直接提取我们要查找的关键字
$ docker inspect hellodocker.web.nginx | grep IPAddress
            "SecondaryIPAddresses": null,
            "IPAddress": "192.168.0.5",
                    "IPAddress": "192.168.0.5",

从上面可以看到我的Web容器运行在宿主机的192.168.0.5:5000。下面我们配置Nginx转发请求到192.168.0.5:5000即可完成反向代理。

Nginx配置反向代理的配置文件路径为:/etc/nginx/conf.d/default.conf。
我们可以通过本地创建一个配置文件挂载到Nginx的容器内部进行反向代理配置。

$ cd demo
$ mkdir nginx
//创建my_nginx.conf文件
$ touch my_nginx.conf
$ vi my_nginx.conf
server {
  listen 80;

  location / {
    proxy_pass http://192.168.0.5:5000;
  }
}

上面我们通过指定listen配置nginx去监听80端口,指定proxy_pass为我们Web容器的IP和端口完成反向代理文件的配置。
接下来就是启动一个新的Nginx容器并通过挂载的方式将配置文件共享到容器内部。

$ docker run -d -p 8080:80 
> -v $HOME/demo/nginx/my_nginx.conf:/etc/nginx/conf.d/default.conf 
> nginx
95381aa56a336f65b6d01ff9964ae3364f37d25e5080673347c1878b3a5bb514
/usr/bin/docker-current: Error response from daemon: driver failed programming external connectivity on endpoint elated_mccarthy (5a576d5991dd164db69b1c568c94c15e47ec7c67e43a3dd6982a2e9b83b60e08): Bind for 0.0.0.0:8080 failed: port is already allocated.

我们发现容器启动失败,原因是8080端口被我们刚刚第一次启动的nginx容器占用了。怎么办?两个方法:第一种就是将刚才创建的nginx容器干掉;第二种就是映射到新的端口。这里选择第一种。

$ docker ps
1bd630b60019        nginx                          "nginx -g 'daemon off"   59 minutes ago      Up 59 minutes       0.0.0.0:8080->80/tcp             hellonginx
//使用docker rm <container id>删除容器,指定-f进行强制删除
$ docker rm 1bd630b60019 -f
//重新启动Nginx容器
$ docker run -d -p 8080:80 
> -v $HOME/demo/nginx/my_nginx.conf:/etc/nginx/conf.d/default.conf 
> nginx
793d4c62ec8ac4658d75ea0ab4273a0b1f0a9a68f9708d2f85929872888b121d

启动成功后,我们再在浏览器中访问http://:8080,发现返回的不再是Nginx的默认欢迎页,而是我们启动的Web容器中运行的MVC的首页,说明反向代理配置成功!

未分类

5. Docker Compose让一切更简单

上面的步骤虽然简单,但要分两步进行:第一个就是我们的Web和Nginx要分两次部署,第二个就是我们必须知道Web容器的IP和端口号,以完成反向代理文件的配置。

对于需要多个容器(比如需要Nginx、SqlServer、Redis、RabbitMQ等)协调运行的复杂应用中,使用以上方式进行部署时,很显然会很麻烦,而且还要为各个容器之间的网络连接而苦恼。
还好,Docker体贴的为我们想到了这一点。借助Compose模块,我们可以编写一个docker-compose.yml文件,使用声明性语法启动一系列相互连接的容器,即可一步完成上面的任务。

Docker Compose是一个用来定义和运行复杂应用的Docker工具。使用Compose,你可以在一个文件中定义一个多容器应用,然后使用一条命令来启动你的应用,完成一切准备工作。

5.1. 安装Docker Compose

依次执行以下命令:

$ sudo curl -L https://github.com/docker/compose/releases/download/1.18.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose
$ docker-compose --version
docker-compose version 1.18.0, build 1719ceb

5.2. 编写第一个docker-compose.yml

dockers-compose.yml文件要定义在我们项目的文件夹下,我们的项目文件夹位于$HOME/demo/HelloDocker.Web。

$ cd $HOME/demo/HelloDocker.Web
$ touch docker-compose.yml
$ vi docker-compose.yml
version: '2'
services:
    hellodocker-web:
        container_name: hellodocker.web.compose
        build: .

    reverse-proxy:
        container_name: reverse-proxy
        image: nginx
        ports:
         - "9090:8080"
        volumes:
         - ./proxy.conf:/etc/nginx/conf.d/default.conf

简单介绍下上面的配置文件,其中定义了两个服务:一个是hellodocker-web,即以我们当前项目目录来构建镜像并启动一个叫hellodocker.web.compose的容器。一个是reverse-proxy,用来使用nginx镜像进行反向代理,其中又通过指定volumes来使用挂载的方式进行配置。

$ touch proxy.conf
$ vi proxy.conf
server {
    listen 8080;

    location / {
      proxy_pass http://hellodocker-web:5000;
    }
}
$ ls
[root@iZ288a3qazlZ HelloDocker.Web]# ls
appsettings.Development.json  Controllers             Models      Startup.cs
appsettings.json              docker-compose.yml      obj         Views
bin                           Dockerfile              Program.cs  wwwroot
bundleconfig.json             HelloDocker.Web.csproj  proxy.conf
[root@iZ288a3qazlZ HelloDocker.Web]#

其中要注意反向代理的配置:proxy_pass http://hellodocker-web:5000;,其中ip部分直接指定的是docker-compose.yml中定义的第一个服务的名称hellodocker-web。
下面我们就来启动Compose:

$ docker-compose up -d
Building hellodocker-web
Step 1 : FROM microsoft/dotnet:latest
 ---> 7d4dc5c258eb
Step 2 : WORKDIR /app
 ---> Using cache
 ---> 98d48a4e278c
Step 3 : COPY . /app
 ---> 0cb9fc540afe
Removing intermediate container 9fecf088f03f
Step 4 : RUN dotnet restore
 ---> Running in 4bb7f34edbbe
  Restore completed in 597.13 ms for /app/HelloDocker.Web.csproj.
  Restoring packages for /app/HelloDocker.Web.csproj...
  Restore completed in 1.76 sec for /app/HelloDocker.Web.csproj.
 ---> 6869609ece23
Removing intermediate container 4bb7f34edbbe
Step 5 : EXPOSE 5000
 ---> Running in a97febf01e5a
 ---> 9b2639862a94
Removing intermediate container a97febf01e5a
Step 6 : ENV ASPNETCORE_URLS http://*:5000
 ---> Running in 4e2f4af28a8d
 ---> 0069661e891a
Removing intermediate container 4e2f4af28a8d
Step 7 : ENTRYPOINT dotnet run
 ---> Running in cbbf08d906f9
 ---> 0bbeef249b30
Removing intermediate container cbbf08d906f9
Successfully built 0bbeef249b30
WARNING: Image for service hellodocker-web was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Creating hellodocker.web.compose ... done
Starting reverse-proxy ... done
//执行docker-compose ps验证启动的服务
$ docker-compose ps
         Name                   Command          State               Ports
---------------------------------------------------------------------------------------
hellodocker.web.compose   dotnet run             Up      5000/tcp
reverse-proxy             nginx -g daemon off;   Up      80/tcp, 0.0.0.0:9090->8080/tcp
//使用curl指令验证nginx的反向代理
$  curl -I http://localhost:9090
HTTP/1.1 200 OK
Server: nginx/1.13.7
Date: Sun, 24 Dec 2017 04:37:35 GMT
Content-Type: text/html; charset=utf-8
Connection: keep-alive

可以看到,通过执行curl -I http://localhost:9090验证代理服务器配置成功,我们再通过浏览器访问http://:9090发现正确返回了我们MVC项目的默认首页。

// 查看当前运行的容器
$ docker ps
CONTAINER ID        IMAGE                            COMMAND                  CREATED             STATUS              PORTS                            NAMES
a52830499cff        hellodockerweb_hellodocker-web   "dotnet run"             7 minutes ago       Up 7 minutes        5000/tcp                         hellodocker.web.compose
e1fe109e10bc        nginx                            "nginx -g 'daemon off"   11 minutes ago      Up 4 minutes        80/tcp, 0.0.0.0:9090->8080/tcp   reverse-proxy

我们同时也发现通过docker-compose正确的创建了两个容器hellodocker.web.compose和reverse-proxy。

6. 最后

经过以上的练习,我们对Nginx有了一定的了解,且知道如何进行配置。同时了解了如何借助docker-compose打包运行需要多容器的复杂应用。

使用 logstash + kafka + elasticsearch 实现日志监控

在本文中,将介绍使用 logstash + kafka + elasticsearch 实现微服务日志监控与查询。

服务配置

添加 maven 依赖:

<dependency>
   <groupId>org.apache.kafka</groupId>
   <artifactId>kafka-clients</artifactId>
   <version>1.0.0</version>
</dependency>

添加 log4j2 配置:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
  <Appenders>
    <Console name="Console" target="SYSTEM_OUT">
      <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
    </Console>
    <Kafka name="Kafka" topic="mcloud-log">
      <PatternLayout pattern="%date %message"/>
      <Property name="bootstrap.servers">localhost:9092</Property>
    </Kafka>
  </Appenders>
  <Loggers>
    <Root level="debug">
      <AppenderRef ref="Console"/>
      <AppenderRef ref="Kafka"/>
    </Root>
    <Logger name="org.apache.kafka" level="INFO" />
  </Loggers>
</Configuration>

系统配置

Zookeeper-3.4.10

官网: http://zookeeper.apache.org/doc/current/zookeeperStarted.html#sc_InstallingSingleMode

添加配置

在 conf 目录下创建配置文件 zoo.cfg , 并在其中添加以下内容:

tickTime=2000
dataDir=/var/lib/zookeeper
clientPort=2181

启动 ZooKeeper

windows:

bin/zkServer.bat start

Kafka_2.11-1.0.0

官网: http://kafka.apache.org/quickstart

修改日志存储位置

config/server.properties

log.dirs=D:/kafka-logs

启动 Kafka

windows:

bin/windows/kafka-server-start.bat config/server.properties

注:

如果在启动的时候出现以下错误:

错误: 找不到或无法加载主类

需要手动修改 bin/windows/kafka-run-class.bat ,找到以下的代码:

set COMMAND=%JAVA% %KAFKA_HEAP_OPTS% %KAFKA_JVM_PERFORMANCE_OPTS% %KAFKA_JMX_OPTS% %KAFKA_LOG4J_OPTS% -cp %CLASSPATH% %KAFKA_OPTS% %*

将其中的 %CLASSPATH% 添上双引号 => “%CLASSPATH%” 。

Elasticsearch-6.1.1

官网: https://www.elastic.co/downloads/elasticsearch

安装 x-pack

bin/elasticsearch-plugin install x-pack

新增用户:

bin/users useradd mcloud-user

修改角色:

bin/users roles -a logstash_admin mcloud-log-user

注:

系统内置角色:

Known roles: [kibana_dashboard_only_user, watcher_admin, logstash_system, kibana_user, machine_learning_user, remote_monitoring_agent, machine_learning_admin, watcher_user, monitoring_user, reporting_user, kibana_system, logstash_admin, transport_client, superuser, ingest_admin]

启动服务

bin/elasticsearch.bat

Kibana-6.1.1

官网: https://www.elastic.co/downloads/kibana

安装 x-pack

bin/kibana-plugin.bat install x-pack

启动服务

bin/kibana.bat

Logstash-6.1.1

官网: https://www.elastic.co/downloads/logstash

创建配置文件

文档: https://www.elastic.co/guide/en/logstash/current/input-plugins.html

config/logstash.conf

input {     
    logstash-input-kafka {
        topics => ["mcloud-log"]
    } 
}
output {
  elasticsearch { 
    hosts => ["localhost:9200"] 
    user => "mcloud-user"
    password => 123456
  }
}

最终效果

相关服务启动完成后, 登陆 kibana 管理界面,可以看到以下的效果:

未分类

源码

源码: https://github.com/heyuxian/mcloud

使用 Filebeat 收集日志并提交到 logstash 中

安装 Filebeat

此处只介绍 Windows 下面的安装,至于其他系统, 请参考: https://link.jianshu.com/?t=https%3A%2F%2Fwww.elastic.co%2Fguide%2Fen%2Fbeats%2Ffilebeat%2Fcurrent%2Ffilebeat-installation.html

下载并解压后,有两种方式运行,一种是注册为 Windows 服务,另一种是直接通过命令行运行;下面分别介绍两种方式。

注册为 Windows 服务

前提:系统必须有 PowerShell,因为官方安装包中提供的脚本只能在 PowerShell 中运行,若是 win10 系统,可忽略,因为它已经自带了 PowerShell, 否则请下载 PowerShell 并安装。

  1. 下载安装包 点我下载.

  2. 解压到以下目录: C:Program Files 。

  3. 重命名 filebeat–windows 为 Filebeat 。

  4. 以 管理员 身份运行 PowerShell 。

  5. 在 PowerShell 中运行以下命令:

cd 'C:Program FilesFilebeat'
C:Program FilesFilebeat> .install-service-filebeat.ps1

注:

如果此处提示你没有权限,请运行以下的命令注册 Filebeat 服务 :

PowerShell.exe -ExecutionPolicy UnRestricted -File .install-service-filebeat.ps1

到这,已经将 Filebeat 成功注册为系统服务,当下一次开机时它会自动启动,当然你也可以手动通过服务控制面板启动它。

通过命令行运行 Filebeat

通过命令行运行 Filebeat 非常简单,只需将 Filebeat 文件解压到某个目录后,通过以下命令运行:

filebeat -e -c filebeat.yml

配置 Filebeat

日志输入配置

Filebeat 使用了安装目录下的 filebeat.yml 文件进行相关配置。此处我们主要会用到以下的配置:

filebeat.prospectors:
- type: log
# 此处需特别注意,官方默认配置为 false,需要修改为 true
  enabled: true
  paths:
  # 此处配置的是需要收集的日志所在的位置,可使用通配符进行配置
    - D:/logs/*.log

日志输出配置

因为我们使用的是 logstash 收集日志,所以得注释掉默认的 elasticsearch 配置,并取消 logstash 的注释,最终的效果为:

#output.elasticsearch:
  # Array of hosts to connect to.
  #hosts: ["localhost:9200"]

  # Optional protocol and basic auth credentials.
  #protocol: "https"
  #username: "elastic"
  #password: "changeme"
output.logstash:
  # The Logstash hosts
  hosts: ["localhost:5044"]

  # Optional SSL. By default is off.
  # List of root certificates for HTTPS server verifications
  #ssl.certificate_authorities: ["/etc/pki/root/ca.pem"]

  # Certificate for SSL client authentication
  #ssl.certificate: "/etc/pki/client/cert.pem"

  # Client Certificate Key
  #ssl.key: "/etc/pki/client/cert.key"

此处仅介绍了最基础的配置,如需查看更多高级配置,请查看:官方文档

关于 Filebeat 的配置已经介绍完毕,下面我介绍 log4j2 的配置。

配置 Log4j2

因为我们使用的是 Filebeat 进行日志收集,所以我们只需要简单的将日志输出到本地文件中即可,这里我将使用 RollingFile 进行相关配置:

log4j-spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
  <Properties>
    <Property name="pattern" value="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
  </Properties>
  <Appenders>
    <Console name="Console" target="SYSTEM_OUT">
      <PatternLayout pattern="${pattern}"/>
    </Console>
    <RollingFile name="RollingFile" fileName="D:/logs/app.log"
      filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">
      <PatternLayout pattern="${pattern}"/>
      <Policies>
        <TimeBasedTriggeringPolicy />
        <SizeBasedTriggeringPolicy size="250 MB"/>
      </Policies>
    </RollingFile>
    <Async name="AsyncRollingFile">
      <AppenderRef ref="RollingFile"/>
    </Async>
  </Appenders>
  <Loggers>
    <Root level="DEBUG">
      <AppenderRef ref="Console"/>
      <AppenderRef ref="AsyncRollingFile"/>
    </Root>
  </Loggers>
</Configuration>

配置 logstash

这里我们只需要在加入以下的配置即可:

input {
  beats {
    port => 5044
  }
}

此处的端口需要和 Filebeat 中配置的端口一致。

好了,所有的配置都已经完成,这里就不再重复 kibana 和 elasticsearch 的配置了,如有需要,请查看: https://www.jianshu.com/p/78c5159aace8

运行效果

我们启动其它服务并登陆 kibana 后,就可以看到以下的结果了:

未分类

查看源码

关于 Filebeat 的介绍就到此结束了,关于 logstash 的更多高级功能将在后续文章中一一介绍。

查看源码: https://link.jianshu.com/?t=https%3A%2F%2Fgithub.com%2Fheyuxian%2Fmcloud

grep命令实例详解——全局正则表达式输出神器

概述

所有的类linux系统都会提供一个名为grep(global regular expression print,全局正则表达式输出)的搜索工具。grep命令在对一个或多个文件的内容进行基于模式的搜索的情况下是非常有用的。模式可以是单个字符、多个字符、单个单词、或者是一个句子。

当命令匹配到执行命令时指定的模式时,grep会将包含模式的一行输出,但是并不对原文件内容进行修改。

在本文中,我们将会讨论到grep命令实例详解。

实例详解

例1 在文件中查找模式(单词)

在/etc/passwd文件中查找单词linuxtechi

root@Linux-world:~# grep linuxtechi /etc/passwd
linuxtechi:x:1000:1000:linuxtechi,,,:/home/linuxtechi:/bin/bash
root@Linux-world:~#

例2 在多个文件中查找模式

root@Linux-world:~# grep linuxtechi /etc/passwd /etc/shadow /etc/gshadow
/etc/passwd:linuxtechi:x:1000:1000:linuxtechi,,,:/home/linuxtechi:/bin/bash
/etc/shadow:linuxtechi:$6$DdgXjxlM$4flz4JRvefvKp0DG6re:16550:0:99999:7:::/etc/gshadow:adm:*::syslog,linuxtechi
/etc/gshadow:cdrom:*::linuxtechi
/etc/gshadow:sudo:*::linuxtechi
/etc/gshadow:dip:*::linuxtechi
/etc/gshadow:plugdev:*::linuxtechi
/etc/gshadow:lpadmin:!::linuxtechi
/etc/gshadow:linuxtechi:!::
/etc/gshadow:sambashare:!::linuxtechi

例3 使用-l参数列出包含指定模式的文件的文件名

root@Linux-world:~# grep -l linuxtechi /etc/passwd /etc/shadow /etc/fstab /etc/mtab
/etc/passwd
/etc/shadow

例4 使用-n参数,在文件中查找指定模式并显示匹配行的行号

root@Linux-world:~# grep -n linuxtechi /etc/passwd
39:linuxtechi:x:1000:1000:linuxtechi,,,:/home/linuxtechi:/bin/bash

例5 使用-v参数输出不包含指定模式的行

输出/etc/passwd文件中所有不含单词“linuxtechi”的行

root@Linux-world:~# grep -v linuxtechi /etc/passwd

例6 使用^符号输出所有以某指定模式开头的行

Bash脚本将^符号视作特殊字符,用于指定一行或者一个单词的开始。例如输出/etc/passwd文件中所有以“root”开头的行

root@Linux-world:~# grep ^root /etc/passwd
root:x:0:0:root:/root:/bin/bash

例7 使用$符号输出所有以指定模式结尾的行

输出/etc/passwd文件中所有以bash结尾的行

root@Linux-world:~# grep bash$ /etc/passwd
root:x:0:0:root:/root:/bin/bash
linuxtechi:x:1000:1000:linuxtechi,,,:/home/linuxtechi:/bin/bash

Bash脚本将美元$符号视作特殊字符,用于指定一行或者一个单词的结尾。

例8 使用-r参数递归地查找特定模式

root@Linux-world:~# grep -r linuxtechi /etc/
/etc/subuid:linuxtechi:100000:65536
/etc/group:adm:x:4:syslog,linuxtechi
/etc/group:cdrom:x:24:linuxtechi
/etc/group:sudo:x:27:linuxtechi
/etc/group:dip:x:30:linuxtechi
/etc/group:plugdev:x:46:linuxtechi
/etc/group:lpadmin:x:115:linuxtechi
/etc/group:linuxtechi:x:1000:
/etc/group:sambashare:x:131:linuxtechi
/etc/passwd-:linuxtechi:x:1000:1000:linuxtechi,,,:/home/linuxtechi:/bin/bash
/etc/passwd:linuxtechi:x:1000:1000:linuxtechi,,,:/home/linuxtechi:/bin/bash
............................................................................

上面的命令将会递归的在/etc目录中查找linuxtechi单词

例9 使用grep查找文件中所有的空行

root@Linux-world:~# grep ^$ /etc/shadow

由于/etc/shadow文件中没有空行,所以没有任何输出

例10 使用-i参数查找模式

grep命令的-i参数在查找时忽略字符的大小写。

我们来看一个例子,在passwd文件中查找LinuxTechi单词。

nextstep4it@localhost:~$ grep -i LinuxTechi /etc/passwd
linuxtechi:x:1001:1001::/home/linuxtechi:/bin/bash
nextstep4it@localhost:~$

例11 使用-e参数查找多个模式

例如,我想在一条grep命令中查找linuxtechi和root单词,使用-e参数,我们可以查找多个模式。

root@Linux-world:~# grep -e "linuxtechi" -e "root" /etc/passwd
root:x:0:0:root:/root:/bin/bash
linuxtechi:x:1000:1000:linuxtechi,,,:/home/linuxtechi:/bin/bash

例12 使用-f用文件指定待查找的模式

首先,在当前目录中创建一个搜索模式文件grep_pattern,我想文件中输入的如下内容。

root@Linux-world:~# cat grep_pattern
^linuxtechi
root
false$

现在,试试使用grep_pattern文件进行搜索

root@Linux-world:~# grep -f grep_pattern /etc/passwd

未分类

例13 使用-c参数计算模式匹配到的数量

继续上面例子,我们在grep命令中使用-c命令计算匹配指定模式的数量

root@Linux-world:~# grep -c -f grep_pattern /etc/passwd
22

例14 输出匹配指定模式行的前或者后面N行

  • 使用-B参数输出匹配行的前4行
root@Linux-world:~# grep -B 4 "games" /etc/passwd

未分类

  • 使用-A参数输出匹配行的后4行
root@Linux-world:~# grep -A 4 "games" /etc/passwd

未分类

  • 使用-C参数输出匹配行的前后各4行
root@Linux-world:~# grep -C 4 "games" /etc/passwd

未分类

例15 grep搜索目录时,排除某些目录

使用grep搜索目录时,会将一些隐藏目录也给搜进去,比如.git目录,如何在使用grep时排除这些目录

使用 –exclude-dir 选项。

语法

--exclude-dir=DIR
Exclude directories matching the pattern DIR from recursive searches.
  • 单个目录示例
grep -E "http"  ./ -R --exclude-dir=.git
  • 多个目录示例
grep -E "http"  . -R --exclude-dir={.git,res,bin}
  • 多个文件示例排除扩展名为 java 和 js 的文件
grep -E "http"  . -R --exclude=*.{java,js}

例16 使用-L参数列出包含指定模式的文件的文件名

逆转输出,使用-L选项来输出那些不匹配的文件的文件名

grep -L "word" filename
grep -L root /etc/*

如何解决vsftpd下显示的时间与系统时间不一致

vsftpd在安全性、高性能及稳定性三个方面有上佳的表现。它提供的主要功能包括虚拟IP设置、虚拟用户、 Standalone、inetd操作模式、强大的单用户设置能力及带宽限流等。就是这么好的程序,有时候也能发生小错误:vsftpd下显示的时间与系 统时间不一致,怎么办呢,我来帮你解答!

ftp上来显示的时间与系统时间不一致,是因为默认情况下,vsftpd 是用GMT做为它的时间的,所以和系统的时间可能会不一致。修改也很简单:

vi /etc/vsftpd/vsftpd.conf

在最后加入一行:

use_localtime=YES

存盘后,重启vsftpd:

service vsftpd restart

这样就行了。

一眼看完文章,是不是觉的小菜一碟,检查下你的vsftpd,是否有类似的错误,赶快动手吧!

centos 7 vsftpd服务器搭建及本地用户

centos 7 vsftpd服务器搭建及本地用户

1. 安装vsftpd server端

yum install -y vsfptd

2. 安装ftp客户端

yum install -y ftp

3. 编辑配置文件/etc/vsftp/vsftpd.conf

sudo cp /etc/vsftp/vsftpd.conf /etc/vsftpd/vsftpd.conf.bak
sudo vim /etc/vsftpd/vsftpd.conf

local_enable=YES
write_enable=YES
local_umask=022
dirmessage_enable=YES
xferlog_enable=YES
connect_from_port_20=YES
xferlog_std_format=YES
ascii_upload_enable=YES
ascii_download_enable=YES
ftpd_banner=Welcome to FTP service
chroot_local_user=YES
ls_recurse_enable=YES
listen=YES
pam_service_name=vsftpd
userlist_enable=YES
local_root=/home/vsftpd
allow_writeable_chroot=YES
tcp_wrappers=YES
sudo useradd ftpuser -s /sbin/nologin

sudo echo "ftpduserpass" |passwd -stdin ftpuser

4. 创建ftp目录

mkdir -p /home/vsftpd
chown -R ftpuser /home/vsftpd
chmod -R 755 /home/vsftpd

5. 启动服务

systemctl start vsftpd
systemctl enable vsftpd

6. 放通防火墙

firewall-cmd --zone = public --add-port = 22/tcp --permanen
firewall-cmd --zone = public --add-port = 21/tcp --permanen
firewall-cmd --reload

7. 测试

ftp localhost

username :ftpuser
password : ftpduserpass

注:记得关闭selinux