月度归档:2017年07月

自建gogs 连接时端口的选择

git推送默认走ssh的22端口,自建的服务通常会跟服务器的22端口冲突,当然这里指的是docker,又看到达人通过转发的方式实现和宿主一同使用22端口,但是实际上咱自建的服务只要配置一下ssh就可以了。这里吐槽一下 git怎么就不能设置默认连接的端口呢???

修改文件:.ssh/config

最后加入如下,1022端口即是docker映射出来的ssh端口,注意Port前有缩进:

Host git.xxx.com

Port 1022

用Docker安装Gogs 取代gitlab -给自己的代码安个家

 

自己搭建gogs服务器原因如下:

  1. 原先用的git.oschina.com,发现免费版对diff有限制,这就算了,对于history版本也有限制,这个就不能忍了,当时没办法只能用本地的github过度了一下;
  2. 发现gitlab有docker版本,开心啊,配置就省心多了,于是开始架设gitlab dockerise服务;
  3. 穷人来说只能用一台入门的ecs 1gb ram +1 core,结果gitlab搞笑的告诉我它至少需要3g ram,至少1g ram+2g swap,只是一个git服务而已,我的天;
  4. gitlab用的uncorn很吃内存,但是服务100+用户没问题,咱私人的不需要这么强,而且它依赖的是企业级的架构:nginx+redis+sidekiq +rails++unicorn+postgresql 应该没有列完,换mysql还挺麻烦的;
  5. 官方docker打包了上面提到的服务,大小居然达到了1.1GB;
  6. gogs是用go写的,go可是堪比c++的性能,功能强大,后来试用后功能堪比github,大小只有128MB,兼容三大数据库,sqlite也支持,这个要赞一个,意味着在树莓派上也是妥妥的,最近go的应用真是如火如荼呀,架设好后内存只吃了30MB,良心项目~;)
  7. 近2万~星,应该是国人写的,骄傲一个;

直接说安装步骤吧(ubuntu):

安装docker和docker-compose:

apt-get install docker -y && pip install docker-compose

创建一个存放gogs数据的地方:

mkdir -p /srv/gogs

创建docker-compose.yml  :

nano docker-compose.yml

配置如下:

</pre><pre>gogs:
  image: gogs/gogs
  container_name: gogs
  depends_on:
    - db
  ports:
    - "3000"
  ports:
    - "10022:22"
  volumes:
    - "/srv/gogs:/data"</pre><pre>

上面depends_on部分里的db是我的mysql服务,如果你的mysql服务不是dockerise的话请删掉这部分。

最后运行服务:

docker-compose up

上面只是最简单的配置,它还内置了nginx,所以既可以直接访问上面的3000端口(甚至指定证书)也可以跟现有的nginx再次代理本地80端口转发。

服务起来后就可以初始化配置了,默认注册的第一个账户为管理员账户,数据库信息跟其他服务一样,需要先建好它用的库和用户即可。初始化页面配置的都是必须的选项,比较简单,安装好后可以在控制面板看到很多设置信息,但是是不能更改的,估计是开发者偷懒,我很理解,我也会这样,呵呵。需要修改的话按照上面的配置是在主机的/srv/gogs/gogs/conf/app.ini中修改,详细的配置项在:https://gogs.io/docs/advanced/configuration_cheat_sheet 修改后docker-compose restart gogs即可

 

Docker 错误:network xxx id xxxx has active endpoints

Docker 总是会碰到各种问题,很多甚至完全找不到原因。docker cli确实不可靠,有时候已经显示了done,但是并没有生效,好在docker开发如火如荼,碰到的问题也会越来越少。docker 碰到问题后常用的办法就是删掉所有container和networks然后重启就好了,这里不会丢掉任何数据。这里不得不说“-f”这个神奇的参数,比如docker rm xxx失败可能是因为没有stop掉,但是如果-f了它会自己stop,完了还总是出错,出错就出错吧,container还是能被删掉,好奇怪的东西。

回归主题,出现这个错误后我把所有容器都删除了,结果并没用用使用docker network inspect查看后发现network这边并没有随之删除,好奇怪的bug,难道删除容器时network就这么无视么。这里要用docker network disconnect -f [networkid] [containerid] 来删除,下面写了一个脚本,disconnect所有network下的所有容器,并删除所有容器。

docker network ls -q | while read networkid; do
        echo "network:$networkid"
        docker network inspect $networkid | jq -r '.[0].Containers | keys[]' | while read endpoint; do
                echo "docker network inspect $networkid | jq -r ".[0].Containers[\"$endpoint\"].Name""
                container=$(docker network inspect $networkid | jq -r ".[0].Containers[\"$endpoint\"].Name")
                echo "docker network disconnect -f $networkid $container"
                docker network disconnect -f $networkid $container

        done
done
docker rm -f $(docker ps -a -q)

CUI环境下Selenium+chrome最新headless特性的问题

我的环境:

  • Docker jessie
  • Python 3.4
  • Selenium 3
  • Chrome59
  • chrome webdriver 2.30

官方推荐的使用方法:https://intoli.com/blog/running-selenium-with-headless-chrome/

我的参数是:

options = webdriver.ChromeOptions()
options.binary_location = '/usr/bin/google-chrome'
options.add_argument('--headless')
options.add_argument('--disable-gpu')
options.add_argument('--no-sandbox')
options.add_argument('--window-size=1200x600')

执行官方示例时出现下面的错误:

selenium.common.exceptions.WebDriverException: Message: unknown error: an X display is required for keycode conversions, consider using Xvfb
  (Session info: headless chrome=59.0.3071.86)
  (Driver info: chromedriver=2.30.(8a88bbe0775e2a23afda0ceaf2ef7ee74e822cc5),platform=Linux 4.4.0-49-generic x86_64)

chrome headless时刚更新的特性,搜索到的文章大多都是用的xvfb,只找到一位日本同学绕开了这个问题。其实google官方就有专门说selenimu还不能很好的支持新的headless,实际使用时主要在sendkeys时出错,日本同学用js绕过了这个错误。方法如下:

# driver.get_element_by_css_selector('hoge').sendKeys('fuga') は例外が発生
def _set_value_for_element(selector: str, value: str):
        return 'document.querySelector("{selector}").setAttribute("value", "{value}")'.format(selector=selector, value=value)

driver.get(url)
# sendKeys() を実行すると例外が発生するので、JSを実行する
driver.execute_script(_set_value_for_element(user_name_selector, user_name))
driver.execute_script(_set_value_for_element(user_password_selector, user_password))
driver.find_element_by_css_selector(login_button_selector).click()