diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..c7d916a6d03e5ca7f2af6d2d66d0ef51a6d9928f
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,28 @@
+variables:
+    IMAGE_URL: 'marula.c3sl.ufpr.br:5000/c3sl/agent-gesac'
+    IMAGE_VERSION: '0.1'
+stages:
+    - build
+    - deploy
+
+build:
+    stage: build
+    script:
+        - docker build -t ${IMAGE_URL}:${IMAGE_VERSION} -t ${IMAGE_URL}:latest src
+    tags:
+        - docker
+        - build
+
+deploy:
+    stage: deploy
+    variables:
+        IMAGE_VERSION: ''
+    script:
+        - docker push ${IMAGE_URL}:${IMAGE_VERSION}
+        - docker push ${IMAGE_URL}:latest
+    tags:
+        - docker
+        - build
+    only:
+        - master
+
diff --git a/src/Dockerfile b/src/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..3c68e1486d451a81ed2351aba6af04ad4be211f5
--- /dev/null
+++ b/src/Dockerfile
@@ -0,0 +1,33 @@
+FROM python:3
+
+LABEL author="C3SL - Centro de Computação Científica e Software Livre"
+
+ENV LOG_LEVEL="warn"
+
+# Database configuration
+ENV DB_ENABLED="true"
+ENV DB_NAME="gesac"
+ENV DB_USER="gesac"
+ENV DB_HOST="localhost"
+ENV DB_PASS="changeme"
+ENV DB_PORT="5432"
+
+# Not implemented yet
+ENV API_ENABLED="false"
+
+RUN groupadd -r gesac && useradd --no-log-init -m -r -g gesac gesac
+
+WORKDIR /home/gesac
+
+COPY --chown=gesac:gesac gesacmonit.py .
+COPY --chown=gesac:gesac requirements.txt .
+
+RUN pip install --no-cache-dir -r requirements.txt
+
+RUN chmod +x gesacmonit.py
+
+USER gesac
+
+ENTRYPOINT ["./gesacmonit.py"]
+
+CMD ["-p gesacmonit.pid", "-v"]
diff --git a/src/gesacmonit.py b/src/gesacmonit.py
index 21898170976320d30afbb67321cc8b7cee475c90..37bd55fd58a5f0111508ff20eb859e7a0bbdfcf9 100755
--- a/src/gesacmonit.py
+++ b/src/gesacmonit.py
@@ -27,10 +27,9 @@
 # minutes, comupting the network traffic (download and upload) as a
 # difference between two measures.
 
-import threading, sys, os, psycopg2, math, signal
-import dateutil.parser, dateutil.relativedelta
-import multiprocessing, logging, pickle, re
-import time, requests, json
+import threading, sys, os, psycopg2, math, signal, argparse, multiprocessing
+import logging, pickle, re, time, requests, json, dateutil.parser
+import dateutil.relativedelta
 from psycopg2.pool import PersistentConnectionPool
 from queue import Queue
 from pysnmp.entity.rfc3413.oneliner import cmdgen
@@ -53,12 +52,6 @@ SNMP_PORT = 161
 SNMP_COM_SATELLITE = "public" # for private IPs
 SNMP_COM_TERRESTRIAL = "gesac_mng" # for public IPs
 
-### Logging settings
-LOG_LEVEL = logging.WARNING
-LOG_FILE  = os.getcwd() + "/gesacmonit.log"
-LOG_FORMAT = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
-logging.basicConfig(filename=LOG_FILE, level=LOG_LEVEL, format=LOG_FORMAT)
-
 ### Define new signals
 SIGSLEEP = signal.SIGUSR1
 SIGWAKE = signal.SIGUSR2
@@ -818,10 +811,44 @@ def chunks(l, chunk):
     for i in range(0, len(l), n):
         yield l[i:i+n]
 
-def get_conf(conf_file):
-    """Return a configuration dictionary used to create queries for the API and to Database."""
-    with open(conf_file) as f:
-        data = json.load(f)
+def parser_config(conf_file):
+    """
+        Return a configuration dictionary used to create queries for the API and Database.
+        Priotiry order: env > conf file > default values
+    """
+
+    default_data = {
+	"db_backup_file" : "db.user"
+	, "api_backup_file" : "host.route"
+	, "api_enabled" : False
+	, "db_enabled" : True
+	, "db" : {
+	    "dbname" : "gesac"
+	    , "user" : "gesac"
+	    , "password" : "changeme"
+	    , "host" : "localhost"
+	    , "port" : "5432"
+	}
+	, "api" : {
+	    "host" : "localhost:3000"
+	    , "collect_route" : "api/v1/collect"
+	    , "points_route" : "api/v1/points?params"
+	}
+    }
+
+    if conf_file:
+    	with open(conf_file) as f:
+            data = json.load(f)
+    else:
+        data = default_data
+
+    data['db_enabled'] = bool(os.environ.get('DB_ENABLED', data['db_enabled']))
+    data['db']['dbname'] = os.environ.get('DB_NAME', data['db']['dbname'])
+    data['db']['user'] = os.environ.get('DB_USER', data['db']['user'])
+    data['db']['password'] = os.environ.get('DB_PASS', data['db']['password'])
+    data['db']['host'] = os.environ.get('DB_HOST', data['db']['host'])
+    data['db']['port'] = os.environ.get('DB_PORT', data['db']['port'])
+
     data['collect_url'] = 'http://' + data['api']['host'] + '/' + data['api']['collect_route']
     data['points_url'] = 'http://' + data['api']['host'] + '/' + data['api']['points_route']
     dsn = ''
@@ -959,35 +986,50 @@ def ensure_proccesses_are_running(config, logger, children, points):
 ########################################################################
 if __name__ == '__main__':
 
-    if len(sys.argv) < 3:
-        print("Usage: %s <database config> <pid file>" % sys.argv[0])
-        sys.exit(1)
+    pid_default = '/run/user/{}/gesacmonit.pid'.format(os.getuid())
 
-    logger = logging.getLogger('__main__')
+    parser = argparse.ArgumentParser()
+    parser.add_argument("-c", "--config", help="Location of the configuration file")
+    parser.add_argument("-p", "--pid", default=pid_default, help="Location of the pid file")
+    parser.add_argument("-l", "--log", help="Location of the log file (default: stdout)")
+    parser.add_argument('-v', '--verbose', action='count', default=0, help="Increase the verbose level")
 
-    pid_file = sys.argv[2]
+    args = parser.parse_args()
 
-    ### Save PID of process
-    with open(pid_file, 'w') as pid_file:
-        pid_file.write(str(os.getpid())+ '\n')
+    # Set up logging
+    log_level = ['ERROR', 'WARNING', 'INFO', 'DEBUG']
+    log_level = log_level[min(args.verbose, 3)]
+    log_level = getattr(logging, log_level)
+    log_format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
+    log_file = args.log
 
-    children = []
+    if args.log:
+        try:
+            logging.basicConfig(filename=log_file, level=log_level, format=log_format)
+        except PermissionError:
+            print("ERROR: Permission denied for log file {}".format(log_file))
+            sys.exit(1)
+    else:
+        logging.basicConfig(level=log_level, format=log_format)
+
+    logger = logging.getLogger('__main__')
 
     def exit_handler(signal, frame):
         logger.warning('Stopping main program...')
         sys.exit(0)
 
-    conf_file = sys.argv[1]
+    # Save PID
+    with open(args.pid, 'w') as pid_file:
+        pid_file.write(str(os.getpid())+ '\n')
 
     # Create db connection and get cursor
-    config = get_conf(conf_file)
+    config = parser_config(args.config)
 
     points = get_gesac_points(config, logger)
     if not points:
         logger.error('Error fetching points. Check DB or API connection and try again')
         sys.exit(1)
 
-
     # Get the number of available cores
     cores = multiprocessing.cpu_count()
 
@@ -995,6 +1037,7 @@ if __name__ == '__main__':
     check_and_restore_data(config, logger, [])
 
     # init all processes
+    children = []
     for pts in chunks(points, cores):
         proc = GesacMonit(config, Points(pts))
         proc.start()
diff --git a/src/requirements.txt b/src/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..072b35ef86572f64d3a0c67a5d0333725a91eaaa
--- /dev/null
+++ b/src/requirements.txt
@@ -0,0 +1,13 @@
+certifi==2018.1.18
+chardet==3.0.4
+idna==2.6
+ply==3.11
+psycopg2-binary==2.7.4
+pyasn1==0.4.2
+pycryptodomex==3.5.1
+pysmi==0.2.2
+pysnmp==4.4.4
+python-dateutil==2.7.0
+requests==2.18.4
+six==1.11.0
+urllib3==1.22