Monday, June 12, 2017

Screen in docker with error "Must be connected to a terminal"

I have a running docker container with command /bin/bash --login. When I run the command
$ docker exec -it devsh /bin/bash --login
I can access the container’s Bash, but when I run screen, I got this error:
$ screen
Must be connected to a terminal.
It turns out that I should use docker attach devsh. This command allows me to access the original shell in the container.

Friday, May 26, 2017

Install Cygwin in a script

I built an Intellij docker image based on CentOS 7. To allow my colleagues to use it on Windows, I need to help them to setup a X window system. This post describe how to setup Cygwin/X using a script without user intervention.
To run in Windows, the best choice for the script is PowerShell. PowerShell is powerful, but ugly compared to Bash.
$CygwinDir=<where you want to install Cygwin>
$CygwinPkgsDir=<where the cygwin packages are cached>

function Download($uri, $outfile) {
  $webClient = New-Object System.Net.WebClient
  $Webclient.DownloadFile($uri, $outfile)
}

function Install-CygwinX {
  $setup = "$DownloadDir\setup-x86_64.exe"
  if (!(Test-Path "$setup")) {
    Download `
      -uri "https://cygwin.com/setup-x86_64.exe" `
      -outfile "$setup"
  }

  Start-Process "$setup" -ArgumentList "--site ""http://mirrors.xmission.com/cygwin"" --root ""$CygwinDir"" --packages xorg-server,xhost --no-admin --local-package-dir ""$CygwinPkgsDir"" --upgrade-also --quiet-mode" -Wait -NoNewWindow
}
You can run this command to get the full list of command line options:
Downloads\setup-x86_64.exe --help
Most important command line options of Cygwin setup are:
  • --no-admin: Your user won’t have to be administrator
  • --quiet-mode: The script will run without asking anything
  • --packages: the packages you need to run a Cygwin/X. No package selection is needed.
The PowerShell script will download the setup executable and run it automatically. Here are some thing you need to know:
  • Don’t use Invoke-WebRequest because it is too slow. For Cygwin setup, it is not a big problem because setup-x86_64.exe is small, and Cygwin setup will download the rest package. If you download about 200MB file like ‘Docker Toolbox for Windows’, you will see how slow it is.
  • Use Start-Process to start the setup executable.
    • -Wait makes the script wait until Cygwin setup finished
    • -NoNewWindow is important if you run a .bat file. Without it, your .bat file will run in a separate window, just appear then disappear. If anything is wrong, you have no way to see what is the error message.

Install Docker Toolbox for Windows Automatically

Docker Toolbox for Windows have command line arguments which allows you to install it without user’s involvement.
You can run this command in Windows Command Prompt to get those arguments:
> Downloads\DockerToolbox.exe /HELP
The most useful arguments for automation are: /SILENT, /DIR, /COMPONENTS, and /TASKS.
To know what values for /COMPONENTS and /TASKS, you can run this command
> Downloads\DockerToolbox.exe /SAVEINF=docker_toolbox.inf
[Setup]
Lang=english
Dir=C:\Program Files\Docker Toolbox
Group=Docker
NoIcons=0
SetupType=full
Components=docker,dockermachine,dockercompose,virtualbox,kitematic,git
Tasks=desktopicon,modifypath,upgradevm
If VirtualBox is already installed and I don’t want to install Kitematic, I can run this command, or put the command into the script to skip them. The installation will be automated.
> Downloads\DockerToolbox.exe /COMPONENTS=docker,dockermachine,dockercompose,git /TASKS=desktopicon,modifypath,upgradevm

Thursday, May 11, 2017

Build Git RPM on CentOS 7

I want to use core.hooksPath which supports since 2.9, but the default Git version of CentOS 7.3 is still 1.8.3:

$ yum list git

Available Packages

git.x86_64                        1.8.3.1-6.el7_2.1                         base
I have to compile from the source by myself. It is not hard to find bunch of blogs explain how to do it. For example, https://www.howtoforge.com/how-to-install-the-latest-git-version-on-centos. However, the method mentioned in those blogs is not what I want, a docker image based on centos:7 with the latest Git version. There are questions I don’t know the answers:
  • How can I clean up those required build tools like gcc? I don’t want a larger image size.
  • How can I install Git manuals? I could not remember all commands and parameters. It will be handy to reference by just typing git help xxx.
I believe the clean way is to build Git in RPM and install Git using RPM in my docker image. Sounds easy, but the first problem I had was where to get .spec to build RPM. The Git source code doesn’t have a RPM spec file. I finally found the spec from Redhat. But it is not easy like Gradle or Maven when you build from a RPM spec. You have to know the tools to pull the dependencies. Finally, my method is actually pretty simple after I figured it out all of steps because I made it in a dockerfile. Here are what I did:
  • I created a docker image git-rpm, which builds Git 2.12.2 in RPMs.
  • When running git-rpm in a container, a yum repository server starts.
  • When I build the docker image, I just simply put the local yum repository for Git, and call yum install -y git.
  • For centos:7, the default configuration turns off the manual installation tsflags=nodocs. I need to turn it on using yum --setopt tsflags='' -y install git.
If you want to get those RPMs from docker and put them to a yum repository, you can run docker cp

Monday, October 17, 2016

VNC Viewer

I recently built a desktop for development in my company’s CORP network. By using VNC, I can access the same Gnome session even from home. Just simply connect to VPN, and start a vnc viewer, I can resume what I do at office.
I have a CentOS 6 on my development desktop. I installed RPM pacakages: vnc-server. (TODO: Details about setting up VNC server.)
I tried TigerVNC Viewer, but it was really bad, especially F8 menu key because I use Eclipse, F8 is used a lot when you are debugging. And there is not a pop-up menu bar like VirtualBox when you are in full-screen mode.
RealVNC satisfies all my requirements about VNC:
  • A menu bar
  • Better configuration UI on Windows 7
  • I can write a script to start VNC viewer
    through SSH tunnel make the viewer goes into full-screen mode on my secondary display automatically.
In CORP network, just click the VNC button on Windows’ taskbard, type the password, the viewer is in full-screen mode on my secondary display.
#/bin/bash
set -e

shutdown() {
  if [ -n "$tunnel_pid" ]; then
    kill $tunnel_pid
  fi
}

trap shutdown EXIT

ssh -N -L 5902:localhost:5902 mydev.desktop &
tunnel_pid=$!

~/apps/bin/VNC-Viewer-5.2.1-Windows-64bit.exe \
  --Monitor='\\.\Display2' \
  --FullScreen=1 \
  localhost:2
I also installed cygwin on Windows so that I could use OpenSSH. The script can clean up the SSH tunnel once the script quits.
At home, the network connection is slow. And that script will fail because RealVNC gets timeout. I didn’t find how to make RealVNC wait for a longer time. I just simply run SSH tunnel and viewer separately in different screens of GNU Screen in a Cygwin terminal.
I chose JPEG encode for better performance when I at home.

Sunday, October 9, 2016

Don't set limit nofile to unlimited

After I set nofile to unlimited in /etc/security/limits.d/90-nproc.conf like this,
*          hard    nproc     unlimited
*          hard    nofile    unlimited

*          soft    nproc     unlimited
*          soft    nofile    unlimited
I could not boot into Gnome on my VM running CentOS 6.8 any more. Even I could switch to a terminal using ctrl-alt-F2, I seemed not be able to log in. I reboot the VM using a live-cd ISO. Then mount the file system, after setting to 32K as below, reboot it, the problem was fixed.
*          -    nproc     unlimited
*          -    nofile    32768
Notes:
# find out the logical volume of the hard drive
fdisk -l

# mount the logical volume
mkdir /mnt/hd
mount /dev/mapper/Volume-lv_root /mnt/hd
vi /mnt/hd/etc/security/limits.d/90-nproc.conf

Monday, September 12, 2016

Gradle show dependencies of the specified configuration

I record the method here in case I forget how to show the dependencies for ONLY one configuration like runtime again.
  • Show dependencies for one configuration ONLY: ./gradlew dependencies --configuration runtime
  • Show a task’s arguments: ./gradlew help --task dependencies