viernes, 27 de noviembre de 2015

Managing dockers (and some emacs help)

Docker containers are a great way to isolate an application. You don't need to pollute your host machine with all the dependencies, and makes it easy to deploy it everywhere.

I'm using docker on my local box for some apps I can't (or don't want) to install, one of them being openresty (until there's a guix package (or I manage to create it), I'll keep it that way).  But using docker for local development is a bit more complex than just running an app there.

First, a few tips for using docker for local development:

Using docker without sudo


By default, docker asks for superuser permissions in order to comunicate to docker server. You have to create a user group called docker and add your user to that group. After that, you can run docker commands as your regular user.

Building docker images and running them


In the beginning,I was creating lots of images, because every time you change any code in your app, the image has to be rebuilt. To build an image, being in your app directory (where your Dockerfile is and your code is), you normally do 'docker build .'  Then, after building, the last line of the output contains the hash for that image in a line like: 'Successfully built 01b4cd5d3e'.  you normally want to run it afterwards, so you'll 'docker run -t -i 01b4cd5d3e bash', to get in a console inside it.  I just wrote a couple of shell functions to ease the loop of build and run.

function dbuild {
    export DBUILD=$(docker build . | grep "Successfully built" | col -b | awk '{print $3}')
    echo -n $DBUILD
}

function dattach ()  {
  docker run -t -i $DBUILD bash
}

With this I can save the copypasting of the image id.

There's yet a better trick to not have to rebuild the image every time, which is to mount a directory of the host machine inside the container.  For this to happen, we have to add the '-v' flat to docker run. Now, in the docker file, we'll create a directory for our code to be in, and just mount it the current directory in that place. In my case, the directory is '/opt/apisonator'.
 
function dattach ()  {
  docker run -v $(pwd):/opt/apisonator/:rw -t -i $DBUILD bash
}

With this, we have a pretty slick way to run our code and tests inside docker, with full access to the docker, but also being in synch with the outside.

Sooo.... what about emacs?


In case you have many images and containers, you'll probably want to do bulk actions on them (running them, deleting, etc.). Emacs has 2 modes for interacting with docker: docker.el and docker-tramp.el .

The first one (docker.el) uses tabulated-list to show all docker images and containers in your machine, and allows you to run, pause,kill, push or pull images and containers.

Docker-tramp.el allows you to use tramp to access the files inside the container from your host emacs. That's pretty pretty neat:  c-x c-f //docker:012f23e2fb/var/logs/.... .

Again, emacs saves the day.




viernes, 20 de noviembre de 2015

Mu4e and gmail (multiple accounts)

Using Emacs for reading mails is super neat and all, but honestly, gmail does an amazing job managing mails.  To make things even 'worse', I wrote some small js to ease the process of managing multiple gmail accounts in conkeror.

I tried to replace gmail with gnus multiple times, but it never worked out very well. Mu4e seems the most sensible choice, but I always had issues configuring it for my gmail accounts ("Your IMAP server wants to alert you to the following: Please log in via your web browser:
http://support.google.com/mail/accounts/bing/answer.py?answer=78754 (Failure)" being the last one), but I finally got to solve them.

If you get the "Please log in via your web browser" there are 2 ways of solving it.
  1. As explained here, allow less secure apps, by going to your accouts settings. This may not work in your company account (if they disabled this option)
  2. Add an application password token. By going to your security settings. and adding a new 'application password'. You can use that token in your .offlineimaprc  file.

Once the basic configuration was working, and read pretty much all the docs and blogs on the field, I quickly got annoyed by the 'dashboard' view mu4e offers.  It provides exactly 0 useful info.  So I got rolled up my sleeves and wrote this tiny little function to do my usual actions in mu4e:

I want to know about new mails in both my personal and corporate accounts.

(defun mnew ()
  (interactive)
  (mu4e-headers-search-bookmark "flag:unread AND NOT flag:trashed AND maildir:/raimon@3scale.net/INBOX OR 
                                 flag:unread AND NOT flag:trashed AND maildir:/raimonster@gmail.com/INBOX"))


Not very nice, I know, but for now, it already provides me something I wanted and wasn't quite possible in gmail. also, I don't have to visit the mu4e 'dashboard'.

Ah!, to periodically fetch new mails, for now I'm going with elisp's timer `run-at-time'.

(run-at-time nil (* 60 5) 'mu4e-update-mail-and-index t)

miércoles, 11 de noviembre de 2015

TIL: comint-send-string

I just learned a really powerful elisp function called `comint-send-string' . It's so easy to understand that probably a simple example will be enough.

  (comint-send-string "*shell*" "xclock\n")

Right, it sends a string to a comint buffer named "*shell*". you can use it to easily interact with any inferior process you have in your emacs. that means clojure repls, ruby repls (robe), etc....