Skip to content
Fix Code Error

Docker compose fails to start a service with an error ‘unknown option’ but docker-compose build on the same command is a success

July 12, 2021 by Code Error
Posted By: Anonymous

I have a project which has a docker-compose file and a Dockerfile.
The project is open here GitHub

I’m building a demo project with:

  • Traefik
  • Snort 3
  • A NodeJS API dummy for testing

The issue is that in my Docker file I have a command like this to run on Snort

# Validates the configuration of Snort
RUN ${MY_PATH}/bin/snort -c /etc/snort/etc/snort.lua

# Runs Snort
CMD ["/usr/local/snort/bin/snort", "-i", "eth0", "-c", "/etc/snort/etc/snort.lua", "-A", "fast", "-s", "65535", "-k", "none"]

When I build the project with docker-compose buildthe commands are executed fine and the configuration pass the check.

When I run docker-compose up the service of Snort fails to run with the next error

❯ docker-compose up
Docker Compose is now in the Docker CLI, try `docker compose up`

Starting snort3demo_back-end_1 ... done
Starting traefik               ... done
Recreating snort3demo_snort_1  ... done
Attaching to snort3demo_back-end_1, snort3demo_snort_1, traefik
snort_1          | ERROR: unknown option - /usr/local/snort/bin/snort
snort_1          | FATAL: see prior 1 errors
snort_1          | Fatal Error, Quitting..
back-end_1       | Server ready
snort3demo_snort_1 exited with code 1
traefik          | time="2021-06-07T09:51:57Z" level=info msg="Configuration loaded from flags."

It is no running the command where we have /usr/local/snort/bin/snort but when I build there are no issues.

I don’t know what could be the problem and my compose looks like as follow

version: "3.8"

services:
  snort:
    cap_add:
      - NET_ADMIN
    image: demo-snort3
    env_file:
      - ./config.env
    build:
      context: ./
      dockerfile: snort3.dockerfile
    networks:
      - "demo-net"

  reverse-proxy:
    image: "traefik:v2.4"
    container_name: "traefik"
    restart: always
    command:
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--entrypoints.web.address=:80"
    ports:
      - "80:80"
      - "8080:8080"
    networks:
      - "demo-net"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro

  back-end:
    image: demo-node
    build:
      context: ./
      dockerfile: node.dockerfile
    networks:
      - "demo-net"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.backend.rule=Host(`demo-node.localhost`)"
      - "traefik.http.routers.backend.entrypoints=web"

networks:
  demo-net:

There is any change I need to perform on the compose to make it run correctly or I did any other mistake.

As required Dockerfile

FROM ubuntu:latest

## Install Dependencies
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -yq 
    wget 
    build-essential 
    libpcap-dev 
    libpcre3-dev 
    libnet1-dev 
    zlib1g-dev 
    luajit 
    hwloc 
    libdnet-dev 
    libdumbnet-dev 
    bison 
    flex 
    liblzma-dev 
    openssl 
    libssl-dev 
    pkg-config 
    libhwloc-dev 
    cmake 
    cpputest 
    libsqlite3-dev 
    uuid-dev 
    libcmocka-dev 
    libnetfilter-queue-dev 
    libmnl-dev 
    autotools-dev 
    libluajit-5.1-dev 
    libunwind-dev 
    iproute2 
    net-tools 
    sudo 
    ethtool 
    libtool 
    git 
    autoconf 
    ragel 
    libboost-dev 
    libboost-all-dev 
    systemd 
    libcrypt-ssleay-perl  
    liblwp-useragent-determined-perl 
    && apt-get clean && rm -rf /var/cache/apt/*

# Define working directory.
WORKDIR /opt

# Safec for runtime bounds checks on certain legacy C-library calls
ENV SAFEC_VERSION 02092020
RUN wget https://github.com/rurban/safeclib/releases/download/v02092020/libsafec-${SAFEC_VERSION}.tar.gz 
    && tar xvfz libsafec-${SAFEC_VERSION}.tar.gz 
    && cd libsafec-${SAFEC_VERSION}.0-g6d921f 
    && ./configure  
    && make  
    && sudo make install

# Hyperscan critical to Snort3 operations and performance
# uses to fast pattern matching
# dependencies: PCRE, gperftools, ragel, Boost C++, flatbuffers, colm
ENV PCRE_VERSION 10.37
RUN wget https://ftp.pcre.org/pub/pcre/pcre2-${PCRE_VERSION}.tar.gz 
    && tar xzvf pcre2-${PCRE_VERSION}.tar.gz 
    && cd pcre2-${PCRE_VERSION} 
    && ./configure && make && sudo make install

ENV GP_TOOLS_VERSION 2.9.1
RUN wget https://github.com/gperftools/gperftools/releases/download/gperftools-${GP_TOOLS_VERSION}/gperftools-${GP_TOOLS_VERSION}.tar.gz 
    && tar xzvf gperftools-${GP_TOOLS_VERSION}.tar.gz 
    && cd gperftools-${GP_TOOLS_VERSION} 
    && ./configure && make && sudo make install

ENV HYPERSCAN_VESRSION 5.4.0-2
RUN wget https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/hyperscan/5.4.0-2/hyperscan_5.4.0.orig.tar.gz 
    && tar xvzf hyperscan_5.4.0.orig.tar.gz 
    && mkdir hyperscan-${HYPERSCAN_VESRSION}-build 
    && cd hyperscan-${HYPERSCAN_VESRSION}-build 
    && cmake -DCMAKE_INSTALL_PREFIX=/usr/local ../hyperscan-5.4.0 
    && make && sudo make install

ENV FLATBUFFERS_VESRSION 2.0.0
RUN wget https://github.com/google/flatbuffers/archive/refs/tags/v${FLATBUFFERS_VESRSION}.tar.gz -O flatbuffers-v${FLATBUFFERS_VESRSION}.tar.gz 
    && tar xvzf flatbuffers-v${FLATBUFFERS_VESRSION}.tar.gz 
    && mkdir flatbuffers-build 
    && cd flatbuffers-build 
    && cmake ../flatbuffers-${FLATBUFFERS_VESRSION} 
    && make && sudo make install

# DAQ
ENV DAQ_VERSION 3.0.3
RUN wget https://github.com/snort3/libdaq/archive/refs/tags/v${DAQ_VERSION}.tar.gz 
    && tar xvfz v${DAQ_VERSION}.tar.gz 
    && cd libdaq-${DAQ_VERSION} 
    && ./bootstrap 
    && ./configure 
    && make 
    && make install

RUN ldconfig

# Snort 3.1.0
ENV MY_PATH=/usr/local/snort
ENV SNORT_VERSION 3.1.5.0
RUN wget https://github.com/snort3/snort3/archive/refs/tags/${SNORT_VERSION}.tar.gz 
    && tar xvfz ${SNORT_VERSION}.tar.gz 
    && cd snort3-${SNORT_VERSION} 
    && ./configure_cmake.sh --prefix=${MY_PATH} 
    && cd build 
    && make -j $(nproc) install 

RUN ldconfig

# OpenAppID - Device detection
ENV OPEN_APP_ID 17843
RUN wget https://www.snort.org/downloads/openappid/${OPEN_APP_ID}  -O OpenAppId-${OPEN_APP_ID}.tgz 
    && tar xvfz OpenAppId-${OPEN_APP_ID}.tgz 
    && cp -R odp /usr/local/lib/
 
# For this to work you MUST have downloaded the snort3 subscribers ruleset.
# This has to be located in the directory we are currently in.
ENV SNORT_RULES_SNAPSHOT 3150
COPY snortrules-snapshot-${SNORT_RULES_SNAPSHOT} /opt/

COPY *.sh /opt

RUN mkdir -p /var/log/snort && 
    mkdir -p /usr/local/lib/snort_dynamicrules && 
    mkdir -p /etc/snort && 
    mkdir -p /etc/snort/rules && 
    mkdir -p /etc/snort/preproc_rules && 
    mkdir -p /etc/snort/etc && 

    cp -r /opt/rules /etc/snort && 
    cp -r /opt/so_rules /etc/snort && 
    cp -r /opt/etc /etc/snort && 
    cp -r /opt/builtins /etc/snort && 

    # Custom rules goes to local.rules 
    # Will be copied an external file to Docker
    # COPY local.rules /etc/snort/rules/local.rules
    touch /etc/snort/rules/local.rules && 
    touch /etc/snort/rules/white_list.rules /etc/snort/rules/black_list.rules

# Pulledpork
RUN wget https://github.com/shirkdog/pulledpork/archive/master.tar.gz -O pulledpork-master.tar.gz 
    && tar xzvf pulledpork-master.tar.gz 
    && cd pulledpork-master 
    && cp pulledpork.pl /usr/bin/ 
    && chmod 755 /usr/bin/pulledpork.pl 
    && cp etc/* /etc/snort/ 
    && cpan install LWP::Protocol::https 
    && cpan install Crypt::SSLeay  
    && cpan Mozilla::CA IO::Socket::SSL

# Check Pulledpork was installed
RUN /usr/bin/pulledpork.pl -V && sleep 15

# Pulledpork conf
COPY pulledpork.conf /etc/snort/pulledpork.conf
COPY disablesid.conf /etc/snort/disablesid.conf

# COPY local rules across
COPY /rules/local.rules /etc/snort/rules/local.rules

# Clean up APT when done.
RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 
    /opt/${SNORT_VERSION}.tar.gz /opt/v${DAQ_VERSION}.tar.gz

ENV INTERFACE 'eth0'
ENV LUA_PATH=${MY_PATH}/include/snort/lua/?.lua;;
ENV SNORT_LUA_PATH=${MY_PATH}/etc/snort
ENV PATH="/usr/local/snort/bin:$PATH"

RUN cd /usr/local/snort/bin/ && ls -la && sleep 30

# Network interface service --> Not working
# RUN ls -la /lib/systemd/system/ && sleep 30
# COPY ethtool.service /lib/systemd/system/
# RUN sudo service enable --now ethtool  
#     && sudo service ethtool start

# HOME_NET config --> chage this with the right IP adresses where snort should monitoring
ARG SNORT_HOME_NET="192.168.0.0/16,172.16.0.0/12,10.0.0.0/8,172.17.0.0/16"
RUN sed -i "s#^HOME_NET =.*#HOME_NET = '$SNORT_HOME_NET'#" /etc/snort/etc/snort.lua

# Validate an installation
RUN ${MY_PATH}/bin/snort -c /etc/snort/etc/snort.lua
RUN chmod a+x /opt/*

# Add the script that allows the rules to be updated when the container is running
ARG PPORK_OINKCODE
RUN if [ ! -z $PPORK_OINKCODE ]; then  bash update-rules.sh "$PPORK_OINKCODE"; fi

# Exposed port
EXPOSE 8080
# Let's run snort!
# CMD ["-i", "eth0"]
ENTRYPOINT ["/opt/entrypoint.sh"]
# CMD ["/usr/local/snort/bin/snort", "-d", "-i", "eth0", "-c", "/etc/snort/etc/snort.lua"]
CMD ["/usr/local/snort/bin/snort", "-i", "eth0", "-c", "/etc/snort/etc/snort.lua", "-A", "fast", "-s", "65535", "-k", "none"]

Solution

Your entrypoint is conflicting with the command you want to run:

ENTRYPOINT ["/opt/entrypoint.sh"]
CMD ["/usr/local/snort/bin/snort", "-i", "eth0", "-c", "/etc/snort/etc/snort.lua", "-A", "fast", "-s", "65535", "-k", "none"]

Those get concatenated to execute the following as your container:

/opt/entrypoint.sh /usr/local/snort/bin/snort -i eth0 -c /etc/snort/etc/snort.lua -A fast -s 65535 -k none

And since your entrypoint contains:

#!/bin/sh
exec /usr/local/snort/bin/snort -c /etc/snort/etc/snort.lua "[email protected]"

That becomes the following command to run:

/usr/local/snort/bin/snort -c /etc/snort/etc/snort.lua /usr/local/snort/bin/snort -i eth0 -c /etc/snort/etc/snort.lua -A fast -s 65535 -k none

So snort is correct that it’s receiving the option /usr/local/snort/bin/snort that it doesn’t know what to do with. This only happens when you run the container, the ENTRYPOINT and CMD are not executed when the image is built.

To fix, either remove the ENTRYPOINT, or set CMD to only be the values that would be appended at the end of that exec command.

Answered By: Anonymous

Related Articles

  • Form field border-radius is not working only on the last…
  • How to properly do JSON API GET requests and assign output…
  • How to parse JSON with XE2 dbxJSON
  • The 'compilation' argument must be an instance of…
  • Azure Availability Zone ARM Config
  • Trouble with boxes appearing/hiding based on selection
  • Search match multiple values in single field in…
  • Event Snippet for Google only shows one event while testing…
  • Avoid creating new session on each axios request laravel
  • Octave using 'for' statement to show two animations…

Disclaimer: This content is shared under creative common license cc-by-sa 3.0. It is generated from StackExchange Website Network.

Post navigation

Previous Post:

Paging in sql server for top level query

Next Post:

a-frame click events with angular

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

  • Get code errors & solutions at akashmittal.com
© 2022 Fix Code Error