Search This Blog

Wednesday 10 May 2017

Dockerization of a Golang application

There are several possibilities how to write a Dockerfile for a Golang application. Which one to choose depends on dependencies the application needs.

If the application uses just built in packages, it is possible to have a very minimalistic Dockerfile.


             FROM scratch

             COPY ./goaws /

             CMD ["/goaws"]


Using scratch means we are not basing our image on anything, there is no operating system. This is possible if we do not need to perform any shell operations that require coperation of the OS like mkdir etc.

-------------------------------------------------------------------------------------------------

If there are non built in dependencies, there there are several approaches possible.

a) The first approach bases the new Docker image on an official golang one, downloads all the dependencies, builds the Go binary and starts the application.

There are several gotchas to watch out for:

The application dependencies, whether internal (packages provided within the application) or external (3rd party packages from the Go public repository) need to be in the right place for the build to be able to find them. The paths searched depend on $GOPATH and $GOROOT environment variables. In the golang:1.8 image OS, the $GOPATH is /go. I created a /go/src/github.com/tamarakaufler/goaws directory which allows the Go compiler to find all internal packages during the build. The go get command will install the external packages and we are good to go (excuse the pun).


             FROM golang:1.8

             RUN mkdir -p /go/src/github.com/tamarakaufler/goaws

             COPY . /go/src/github.com/tamarakaufler/goaws/

             RUN go get github.com/ghodss/yaml

             RUN go get github.com/gorilla/mux

             WORKDIR /go/src/github.com/tamarakaufler/goaws

             RUN go build .

             CMD ["./goaws"]


b) Another option is to create an intermediate image based on an official golang one, install various 3rd party packages that your applications need and copy over internal packages. Then:

             FROM my_golang

             COPY ./goaws /

             CMD ["/goaws"]

where my_golang's Dockerfile is:

           FROM golang:1.8

           RUN mkdir -p /go/src/github.com/tamarakaufler/goaws
           COPY ./app/conf/config.go /go/src/github.com/tamarakaufler/goaws/app/conf/
           COPY ./app/router/router.go /go/src/github.com/tamarakaufler/goaws/app/router/

           RUN go get github.com/ghodss/yaml
           RUN go get github.com/gorilla/mux

Saturday 6 May 2017

Dockerization of an sftp service

Synopsis

As part of building a web service, I wanted to have some of the microservice dependencies dockerized for easy setup and deployment. The three applications my web service depends are:

  • mongodb
  • rabbitmq
  • sftp

This post is about dockerizing sftp. The container will provide sftp-only user accounts and the users will be restricted to their home directory. The former is done through disabling login (in the Dockerfile), the latter by chrooting to the user's home directory (in the sshd_config file).


FROM ubuntu:latest

The latest version of ubuntu is our starting point.


RUN apt-get update && \
    apt-get -y install openssh-server


Sftp (SSH File Transfer Protocol) is a separate protocol packaged with SSH, so we install the ssh server.


RUN mkdir /var/run/sshd

Privilege separation directory, /var/run/sshd, must be present, otherwise the container will exit immediately after starting.


COPY sshd_config /etc/ssh/sshd_config

The default ssh configuration is adjusted for sftp purposes (https://github.com/tamarakaufler/go_loyalty_scheme_service/tree/master/dockerized/sftp).


RUN groupadd sftpusers

All sftp users will be part of this group.

 
 

RUN adduser  --quiet --disabled-password sftp_loyalty

When creating a new sftp user, the
--disabled-password option is provided not to have problems with the following command to change the password.


RUN echo "sftp_loyalty:BIGSeCrEt" | chpasswd sftp_loyalty

RUN usermod -g sftpusers sftp_loyalty && \
    usermod -s /bin/nologin sftp_loyalty && \
    chown root:sftp_loyalty /home/sftp_loyalty && \
    chmod 755 /home/sftp_loyalty


This assigns the sftp user to the correct group and disables normal login.


RUN mkdir /home/sftp_loyalty/uploads && \
    chown sftp_loyalty:sftp_loyalty /home/sftp_loyalty/uploads && \
    chmod 755 /home/sftp_loyalty/uploads

EXPOSE 22

CMD ["/usr/sbin/sshd", "-D"]


Starts the ssh server. I originally tried using:   service sshd start
but that did not work, preventing the container from starting.

Update:  Providing the full path:

             /usr/sbin/service sshs start

works

-----------------------------------------------------------------------------------------------------------------
sshd_config (based on the default /etc/ssh/sshd_config)

  1. Deleted the original line:
    1. Subsystem sftp /usr/lib/openssh/sftp-server
  2. Added at the end of the default sshd_config file:
    1. Subsystem sftp internal-sftp
      Match Group sftpusers
             ChrootDirectory %h #set the home directory
             ForceCommand internal-sftp
             X11Forwarding no
             AllowTCPForwarding no
              PasswordAuthentication yes


https://github.com/tamarakaufler/go_loyalty_scheme_service (when it becomes public)


References


https://www.vultr.com/docs/setup-sftp-only-user-accounts-on-ubuntu-14
https://github.com/atmoz/sftp
https://docs.docker.com/engine/examples/running_ssh_service/

Thursday 4 May 2017

Xsane - Falied to open device error

PROBLEM


Unable to open xsane due to an error:

Failed to open device 'brother3:bus4:dev2' Invalid argument

BACKGROUND


Ubuntu 16.04 (upgraded from Ubuntu14:04)
Printer/scanner:       Brother DCP-J315W

SOLUTION


1. Open /etc/udev/rules.d/60-libsane.rules
2. Add the following 2 lines at the last of the device entry. (just before "# The following rule...")
         # Brother scanners
         ATTRS{idVendor}=="04f9", ENV{libsane_matched}="yes" 
3. Restart the OS.

 NOTE


  • idVendor is the same for all Brother printers