3CX inside Docker container

Discussion in '3CX Phone System - General' started by farfui, Nov 20, 2017.

3CX inside Docker container 5 5 1votes
5/5, 1 vote

Thread Status:
Not open for further replies.
  1. farfui

    Joined:
    Nov 20, 2017
    Messages:
    4
    Likes Received:
    2
    Docker hub image: https://hub.docker.com/r/farfui/3cx/

    Running the container

    If you run the container on an APPARMOR enabled machine you have to add "--security-opt apparmor=unconfined" to the run command.

    1. Create a macvlan network. This is an example and you have to translate this command to map your needs.
      Code:
      docker network create \
          -d macvlan \
          --subnet 192.168.1.0/24 \
          --gateway 192.168.1.1 \
          -o parent=eth0 mv_eth0
    • Run the container
      Code:
      docker run \
          -d \
          --hostname {YOUR HOSTNAME} \
          --memory {MEMORY} \
          --memory-swap {SWAP MEMORY} \
          --ip {IP ADDRESS} \
          --network mv_eth0 \
          --restart unless-stopped \
          -v 3cx_backup:/mnt/backup \
          -v 3cx_recordings:/mnt/recordings \
          -v 3cx_log:/var/log \
          -v /sys/fs/cgroup:/sys/fs/cgroup:ro \
          --cap-add SYS_ADMIN \
          --name 3cx \
          farfui/3cx:15.5
    • Setup the timezone. You can find the full listing under "/usr/share/zoneinfo/".
      Code:
      docker exec 3cx timedatectl set-timezone {YOUR ZONE INFO}
    • Start 3CX Wizard for initial setup
      Code:
      docker exec -ti 3cx /usr/sbin/3CXWizard --cleanup
    build.sh - How this container was build
    Code:
    #!/bin/bash
    
    docker build --force-rm --no-cache --build-arg BUILD_STRING="$(date -u)" --build-arg BUILD_DATE="$(date +%d-%m-%Y)" --build-arg  BUILD_TIME="$(date +%H:%M:%S)" -t 3cx_stage1 .
    docker run -d --privileged --name 3cx_stage1_c 3cx_stage1
    docker exec 3cx_stage1_c bash -c \
           "   systemctl mask systemd-logind console-getty.service container-getty@.service getty-static.service getty@.service serial-getty@.service getty.target \
            && systemctl enable nginx exim4 postgresql \
            && echo 1 | apt-get -y install 3cxpbx"
    docker stop 3cx_stage1_c
    docker commit 3cx_stage1_c farfui/3cx:15.5
    docker push farfui/3cx:15.5
    docker rm 3cx_stage1_c
    docker rmi 3cx_stage1
    Dockerfile
    Code:
    FROM debian:stretch
    
    ARG BUILD_STRING
    ARG BUILD_DATE
    ARG BUILD_TIME
    
    LABEL build.string $BUILD_STRING
    LABEL build.date   $BUILD_DATE
    LABEL build.time   $BUILD_TIME
    
    ENV DEBIAN_FRONTEND noninteractive
    ENV LANG en_US.UTF-8
    ENV LANGUAGE en
    ENV container docker
    
    RUN apt-get update \
       && apt-get update -y \
       && apt-get upgrade -y \
       && apt-get install -y --allow-unauthenticated \
            apt-utils \
            wget \
            gnupg2 \
            systemd \
            locales \
       && sed -i 's/\# \(en_US.UTF-8\)/\1/' /etc/locale.gen \
       && locale-gen \
       && wget -O- http://downloads.3cx.com/downloads/3cxpbx/public.key | apt-key add - \
       && echo "deb http://downloads.3cx.com/downloads/debian stretch main" | tee /etc/apt/sources.list.d/3cxpbx.list \
       && apt-get update -y \
       && apt-get install -y --allow-unauthenticated \
          libcurl3=7.38.0-4+deb8u5 \
          $(apt-cache depends 3cxpbx | grep Depends | sed "s/.*ends:\ //" | tr '\n' ' ') \
       && rm -f /lib/systemd/system/multi-user.target.wants/* \
       && rm -f /etc/systemd/system/*.wants/* \
       && rm -f /lib/systemd/system/local-fs.target.wants/* \
       && rm -f /lib/systemd/system/sockets.target.wants/*udev* \
       && rm -f /lib/systemd/system/sockets.target.wants/*initctl* \
       && rm -f /lib/systemd/system/basic.target.wants/* \
       && rm -f /lib/systemd/system/anaconda.target.wants/*
    
    EXPOSE 5015/tcp 5001/tcp 5060/tcp 5060/udp 5061/tcp 5090/tcp 5090/udp 9000-9500/udp
    
    CMD ["/lib/systemd/systemd"]
     
    #1 farfui, Nov 20, 2017
    Last edited: Dec 12, 2017
    kusig and StefanW like this.
  2. StefanW

    StefanW Head of Customer Support and Training
    Staff Member 3CX Support

    Joined:
    Jun 2, 2009
    Messages:
    1,199
    Likes Received:
    79

    nice one, much the same to what I played with, some parts are much nicer handled with the mac vlan.
    Just the repo use this lines:

    wget -O- http://downloads.3cx.com/downloads/3cxpbx/public.key | apt-key add -
    echo "deb http://downloads.3cx.com/downloads/debian stretch main" | tee /etc/apt/sources.list.d/3cxpbx.list
    apt-get install libcurl3=7.38.0-4+deb8u5
    apt-get update
    apt-get install 3cxpbx
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  3. farfui

    Joined:
    Nov 20, 2017
    Messages:
    4
    Likes Received:
    2
    Thank you. I've updated the image in the docker hub and the original post.

    According to this post https://www.3cx.com/blog/docs/linux-version-9-stretch/ we have to install
    libicu52 and libssl1.0.0 . Are they still needed?

    It is not possible to run apt-get install 3cxpbx from within the Dockerfile because 3cx requires a running systemd and you can not run systemd from command line because it must bu run with PID 1, hence you have to build an intermediate image and then run that image and use "docker exec ..." to install 3cxpbx on it. Is it possible to install 3cxpbx without systemd?

    It would be great if we could get rid of the --privileged flag and instead use
    Code:
    --cap-add=SYS_ADMIN –v /sys/fs/cgroup:/sys/fs/cgroup:ro
    which is required for systemd. This would dramatically increase the security of the container. The problem is that 3cx crashes when trying to enumerate the interfaces and more specifically when trying to access the file /sys/class/net/lo/operstate. I suppose that is because docker is automatically enforcing the docker-default apparmor profile https://github.com/moby/moby/blob/master/profiles/apparmor/template.go . One solution would be to rewrite that profile and enforce it with --security-opt apparmor=docker-3cx . Is there more elegant solution to this?
     
  4. StefanW

    StefanW Head of Customer Support and Training
    Staff Member 3CX Support

    Joined:
    Jun 2, 2009
    Messages:
    1,199
    Likes Received:
    79
    no, only libcurl3=7.38.0-4+deb8u5 is needed for strech debian 9
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  5. StefanW

    StefanW Head of Customer Support and Training
    Staff Member 3CX Support

    Joined:
    Jun 2, 2009
    Messages:
    1,199
    Likes Received:
    79
    no and this is a bit the pitfall, Docker is great for a single app running inside of it (Apache+php is still fine). 3CX looks like one but packages 8 different services.
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  6. farfui

    Joined:
    Nov 20, 2017
    Messages:
    4
    Likes Received:
    2
    Yes, better. I also added
    Code:
    ENV LANGUAGE en
    sed -i 's/\# \(en_US.UTF-8\)/\1/' /etc/locale.gen \
    locale-gen \
    PS
    The original post is also edited.
     
  7. farfui

    Joined:
    Nov 20, 2017
    Messages:
    4
    Likes Received:
    2
    There is a little bit more secure method of running the container without --privileged mode. You can disable docker-default apparmor profile with
    Code:
    --security-opt apparmor=unconfined
    and you have to add this
    Code:
    --cap-add SYS_ADMIN -v /sys/fs/cgroup:/sys/fs/cgroup:ro
    for systemd to work correctly.
    That way you will keep enabled seccomp kernel facilities and will not enable all the kernel capabilities.

    PS
    The original post is also edited.
     
Thread Status:
Not open for further replies.